DSDSWeb/static/js/Cesium-1.53/Specs/Core/GeometryPipelineSpec.js

3040 lines
130 KiB
JavaScript

defineSuite([
'Core/GeometryPipeline',
'Core/arraySlice',
'Core/AttributeCompression',
'Core/BoundingSphere',
'Core/BoxGeometry',
'Core/Cartesian2',
'Core/Cartesian3',
'Core/ComponentDatatype',
'Core/Ellipsoid',
'Core/EllipsoidGeometry',
'Core/EncodedCartesian3',
'Core/GeographicProjection',
'Core/Geometry',
'Core/GeometryAttribute',
'Core/GeometryInstance',
'Core/GeometryType',
'Core/Math',
'Core/Matrix4',
'Core/PolygonGeometry',
'Core/PrimitiveType',
'Core/Tipsify',
'Core/VertexFormat'
], function(
GeometryPipeline,
arraySlice,
AttributeCompression,
BoundingSphere,
BoxGeometry,
Cartesian2,
Cartesian3,
ComponentDatatype,
Ellipsoid,
EllipsoidGeometry,
EncodedCartesian3,
GeographicProjection,
Geometry,
GeometryAttribute,
GeometryInstance,
GeometryType,
CesiumMath,
Matrix4,
PolygonGeometry,
PrimitiveType,
Tipsify,
VertexFormat) {
'use strict';
it('converts triangles to wireframe in place', function() {
var geometry = GeometryPipeline.toWireframe(new Geometry({
attributes : {},
indices : [0, 1, 2, 3, 4, 5],
primitiveType : PrimitiveType.TRIANGLES
}));
expect(geometry.primitiveType).toEqual(PrimitiveType.LINES);
var v = geometry.indices;
expect(v.length).toEqual(12);
expect(v[0]).toEqual(0);
expect(v[1]).toEqual(1);
expect(v[2]).toEqual(1);
expect(v[3]).toEqual(2);
expect(v[4]).toEqual(2);
expect(v[5]).toEqual(0);
expect(v[6]).toEqual(3);
expect(v[7]).toEqual(4);
expect(v[8]).toEqual(4);
expect(v[9]).toEqual(5);
expect(v[10]).toEqual(5);
expect(v[11]).toEqual(3);
});
it('converts a triangle fan to wireframe in place', function() {
var geometry = GeometryPipeline.toWireframe(new Geometry({
attributes : {},
indices : [0, 1, 2, 3],
primitiveType : PrimitiveType.TRIANGLE_FAN
}));
expect(geometry.primitiveType).toEqual(PrimitiveType.LINES);
var v = geometry.indices;
expect(v.length).toEqual(12);
expect(v[0]).toEqual(0);
expect(v[1]).toEqual(1);
expect(v[2]).toEqual(1);
expect(v[3]).toEqual(2);
expect(v[4]).toEqual(2);
expect(v[5]).toEqual(0);
expect(v[6]).toEqual(0);
expect(v[7]).toEqual(2);
expect(v[8]).toEqual(2);
expect(v[9]).toEqual(3);
expect(v[10]).toEqual(3);
expect(v[11]).toEqual(0);
});
it('converts a triangle strip to wireframe in place', function() {
var geometry = GeometryPipeline.toWireframe(new Geometry({
attributes : {},
indices : [0, 1, 2, 3],
primitiveType : PrimitiveType.TRIANGLE_STRIP
}));
expect(geometry.primitiveType).toEqual(PrimitiveType.LINES);
var v = geometry.indices;
expect(v.length).toEqual(12);
expect(v[0]).toEqual(0);
expect(v[1]).toEqual(1);
expect(v[2]).toEqual(1);
expect(v[3]).toEqual(2);
expect(v[4]).toEqual(2);
expect(v[5]).toEqual(0);
expect(v[6]).toEqual(2);
expect(v[7]).toEqual(3);
expect(v[8]).toEqual(3);
expect(v[9]).toEqual(1);
expect(v[10]).toEqual(1);
expect(v[11]).toEqual(2);
});
it('toWireframe throws without a geometry', function() {
expect(function() {
GeometryPipeline.toWireframe(undefined);
}).toThrowDeveloperError();
});
it('toWireframe throws when primitiveType is not a triangle type', function() {
expect(function() {
GeometryPipeline.toWireframe(new Geometry({
attributes : {},
indices : [],
primitiveType : PrimitiveType.POINTS
}));
}).toThrowDeveloperError();
});
it('createLineSegmentsForVectors', function() {
var geometry = new Geometry({
attributes : {
position : new GeometryAttribute({
componentDatatype : ComponentDatatype.FLOAT,
componentsPerAttribute : 3,
values : [0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0]
}),
normal : new GeometryAttribute({
componentDatatype : ComponentDatatype.FLOAT,
componentsPerAttribute : 3,
values : [0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0]
})
},
primitiveType : PrimitiveType.TRIANGLES,
boundingSphere : new BoundingSphere(new Cartesian3(0.5, 0.5, 0.0), 1.0)
});
var lines = GeometryPipeline.createLineSegmentsForVectors(geometry, 'normal', 1.0);
var linePositions = [0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0];
expect(lines.attributes).toBeDefined();
expect(lines.attributes.position).toBeDefined();
expect(lines.attributes.position.values).toEqual(linePositions);
expect(lines.primitiveType).toEqual(PrimitiveType.LINES);
expect(lines.boundingSphere.center).toEqual(geometry.boundingSphere.center);
expect(lines.boundingSphere.radius).toEqual(geometry.boundingSphere.radius + 1.0);
});
it('createLineSegmentsForVectors throws without geometry', function() {
expect(function() {
GeometryPipeline.createLineSegmentsForVectors();
}).toThrowDeveloperError();
});
it('createLineSegmentsForVectors throws without geometry.attributes.position', function() {
expect(function() {
GeometryPipeline.createLineSegmentsForVectors();
}).toThrowDeveloperError();
});
it('createLineSegmentsForVectors throws when geometry.attributes does not have an attributeName property', function() {
var geometry = new Geometry({
attributes : {
position : new GeometryAttribute({
componentDatatype : ComponentDatatype.FLOAT,
componentsPerAttribute : 3,
values : [0.0, 1.0, 2.0, 3.0, 4.0, 5.0]
})
},
primitiveType : PrimitiveType.TRIANGLES
});
expect(function() {
GeometryPipeline.createLineSegmentsForVectors(geometry, 'bitangent');
}).toThrowDeveloperError();
});
it('creates attribute indices', function() {
var geometry = new Geometry({
attributes : {
position : new GeometryAttribute({
componentDatatype : ComponentDatatype.FLOAT,
componentsPerAttribute : 3,
values : []
}),
normal : new GeometryAttribute({
componentDatatype : ComponentDatatype.FLOAT,
componentsPerAttribute : 3,
values : []
}),
color : new GeometryAttribute({
componentDatatype : ComponentDatatype.UNSIGNED_BYTE,
componentsPerAttribute : 4,
values : []
})
},
primitiveType : PrimitiveType.TRIANGLES
});
var indices = GeometryPipeline.createAttributeLocations(geometry);
var validIndices = [0, 1, 2];
expect(validIndices).toContain(indices.position);
expect(validIndices).toContain(indices.normal);
expect(validIndices).toContain(indices.color);
expect(indices.position).not.toEqual(indices.normal);
expect(indices.position).not.toEqual(indices.color);
});
it('createAttributeLocations throws without a geometry', function() {
expect(function() {
GeometryPipeline.createAttributeLocations(undefined);
}).toThrowDeveloperError();
});
it('reorderForPreVertexCache reorders all indices and attributes for the pre vertex cache', function() {
var geometry = new Geometry({
attributes : {
weight : new GeometryAttribute({
componentDatatype : ComponentDatatype.FLOAT,
componentsPerAttribute : 1,
values : [0.0, 1.0, 2.0, 3.0, 4.0, 5.0]
}),
positions : new GeometryAttribute({
componentDatatype : ComponentDatatype.FLOAT,
componentsPerAttribute : 3,
values : [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0]
})
},
indices : [5, 3, 2, 0, 1, 4, 4, 1, 3, 2, 5, 0],
primitiveType : PrimitiveType.TRIANGLES
});
GeometryPipeline.reorderForPreVertexCache(geometry);
expect(geometry.indices[0]).toEqual(0);
expect(geometry.indices[1]).toEqual(1);
expect(geometry.indices[2]).toEqual(2);
expect(geometry.indices[3]).toEqual(3);
expect(geometry.indices[4]).toEqual(4);
expect(geometry.indices[5]).toEqual(5);
expect(geometry.indices[6]).toEqual(5);
expect(geometry.indices[7]).toEqual(4);
expect(geometry.indices[8]).toEqual(1);
expect(geometry.indices[9]).toEqual(2);
expect(geometry.indices[10]).toEqual(0);
expect(geometry.indices[11]).toEqual(3);
expect(geometry.attributes.weight.values[0]).toEqual(5.0);
expect(geometry.attributes.weight.values[1]).toEqual(3.0);
expect(geometry.attributes.weight.values[2]).toEqual(2.0);
expect(geometry.attributes.weight.values[3]).toEqual(0.0);
expect(geometry.attributes.weight.values[4]).toEqual(1.0);
expect(geometry.attributes.weight.values[5]).toEqual(4.0);
expect(geometry.attributes.positions.values[0]).toEqual(15);
expect(geometry.attributes.positions.values[1]).toEqual(16);
expect(geometry.attributes.positions.values[2]).toEqual(17);
expect(geometry.attributes.positions.values[3]).toEqual(9);
expect(geometry.attributes.positions.values[4]).toEqual(10);
expect(geometry.attributes.positions.values[5]).toEqual(11);
expect(geometry.attributes.positions.values[6]).toEqual(6);
expect(geometry.attributes.positions.values[7]).toEqual(7);
expect(geometry.attributes.positions.values[8]).toEqual(8);
expect(geometry.attributes.positions.values[9]).toEqual(0);
expect(geometry.attributes.positions.values[10]).toEqual(1);
expect(geometry.attributes.positions.values[11]).toEqual(2);
expect(geometry.attributes.positions.values[12]).toEqual(3);
expect(geometry.attributes.positions.values[13]).toEqual(4);
expect(geometry.attributes.positions.values[14]).toEqual(5);
expect(geometry.attributes.positions.values[15]).toEqual(12);
expect(geometry.attributes.positions.values[16]).toEqual(13);
expect(geometry.attributes.positions.values[17]).toEqual(14);
});
it('reoderForPreVertexCache removes unused vertices', function() {
var geometry = new Geometry({
attributes : {
weight : new GeometryAttribute({
componentDatatype : ComponentDatatype.FLOAT,
componentsPerAttribute : 1,
values : [0.0, 1.0, 2.0, 3.0, 4.0, 5.0]
}),
positions : new GeometryAttribute({
componentDatatype : ComponentDatatype.FLOAT,
componentsPerAttribute : 3,
values : [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0]
})
},
indices : [5, 3, 2, 4, 1, 3],
primitiveType : PrimitiveType.TRIANGLES
});
GeometryPipeline.reorderForPreVertexCache(geometry);
expect(geometry.indices.length).toEqual(6);
expect(geometry.attributes.positions.values.length).toEqual((6 - 1) * 3);
expect(geometry.attributes.weight.values.length).toEqual(6 - 1);
});
it('reorderForPreVertexCache throws without a geometry', function() {
expect(function() {
GeometryPipeline.reorderForPreVertexCache(undefined);
}).toThrowDeveloperError();
});
it('reorderForPreVertexCache throws when attributes have a different number of attributes', function() {
expect(function() {
var geometry = new Geometry({
attributes : {
attribute1 : new GeometryAttribute({
componentDatatype : ComponentDatatype.FLOAT,
componentsPerAttribute : 1,
values : [0, 1, 2]
}),
attribute2 : new GeometryAttribute({
componentDatatype : ComponentDatatype.FLOAT,
componentsPerAttribute : 3,
values : [0, 1, 2, 3, 4, 5]
})
}
});
GeometryPipeline.reorderForPreVertexCache(geometry);
}).toThrowDeveloperError();
});
it('reorderForPostVertexCache reorders indices for the post vertex cache', function() {
var geometry = EllipsoidGeometry.createGeometry(new EllipsoidGeometry());
var acmrBefore = Tipsify.calculateACMR({
indices : geometry.indices,
cacheSize : 24
});
expect(acmrBefore).toBeGreaterThan(1.0);
geometry = GeometryPipeline.reorderForPostVertexCache(geometry);
var acmrAfter = Tipsify.calculateACMR({
indices : geometry.indices,
cacheSize : 24
});
expect(acmrAfter).toBeLessThan(0.7);
});
it('reorderForPostVertexCache throws without a geometry', function() {
expect(function() {
GeometryPipeline.reorderForPostVertexCache(undefined);
}).toThrowDeveloperError();
});
it('fitToUnsignedShortIndicestoThrowDeveloperErrorot change geometry', function() {
var geometry = new Geometry({
attributes : {
time : new GeometryAttribute({
componentDatatype : ComponentDatatype.FLOAT,
componentsPerAttribute : 1,
values : [10.0]
}),
heat : new GeometryAttribute({
componentDatatype : ComponentDatatype.FLOAT,
componentsPerAttribute : 1,
values : [1.0]
})
},
indices : [0, 0, 0],
primitiveType : PrimitiveType.TRIANGLES
});
var geometries = GeometryPipeline.fitToUnsignedShortIndices(geometry);
expect(geometries.length).toEqual(1);
expect(geometries[0]).toBe(geometry);
});
it('fitToUnsignedShortIndices creates one geometry', function() {
var sixtyFourK = CesiumMath.SIXTY_FOUR_KILOBYTES;
var times = [];
for ( var i = 0; i < sixtyFourK + 1; ++i) {
times.push(i);
}
var geometry = new Geometry({
attributes : {
time : new GeometryAttribute({
componentDatatype : ComponentDatatype.FLOAT,
componentsPerAttribute : 1,
values : times
})
},
indices : [0, 0, 0, sixtyFourK, sixtyFourK, sixtyFourK, 0, sixtyFourK, 0],
primitiveType : PrimitiveType.TRIANGLES
});
var geometries = GeometryPipeline.fitToUnsignedShortIndices(geometry);
expect(geometries.length).toEqual(1);
expect(geometries[0].attributes.time.componentDatatype).toEqual(ComponentDatatype.FLOAT);
expect(geometries[0].attributes.time.componentsPerAttribute).toEqual(1);
expect(geometries[0].attributes.time.values).toEqual([0, sixtyFourK]);
expect(geometries[0].primitiveType).toEqual(PrimitiveType.TRIANGLES);
expect(geometries[0].indices).toEqual([0, 0, 0, 1, 1, 1, 0, 1, 0]);
});
it('fitToUnsignedShortIndices creates two triangle geometries', function() {
var sixtyFourK = CesiumMath.SIXTY_FOUR_KILOBYTES;
var positions = [];
for ( var i = 0; i < sixtyFourK + 1; ++i) {
positions.push(i, i, i);
}
var indices = [];
for ( var j = sixtyFourK; j > 1; j -= 3) {
indices.push(j, j - 1, j - 2);
}
indices.push(0, 1, 2);
var geometry = new Geometry({
attributes : {
position : new GeometryAttribute({
componentDatatype : ComponentDatatype.FLOAT,
componentsPerAttribute : 3,
values : positions
})
},
indices : indices,
primitiveType : PrimitiveType.TRIANGLES
});
var geometries = GeometryPipeline.fitToUnsignedShortIndices(geometry);
expect(geometries.length).toEqual(2);
expect(geometries[0].attributes.position.values.length).toEqual(positions.length - 6); // Two vertices are not copied (0, 1)
expect(geometries[0].indices.length).toEqual(indices.length - 3); // One triangle is not copied (0, 1, 2)
expect(geometries[1].attributes.position.values.length).toEqual(9);
expect(geometries[1].indices.length).toEqual(3);
});
it('fitToUnsignedShortIndices creates two line geometries', function() {
var sixtyFourK = CesiumMath.SIXTY_FOUR_KILOBYTES;
var positions = [];
for ( var i = 0; i < sixtyFourK + 2; ++i) {
positions.push(i, i, i);
}
var indices = [];
for ( var j = sixtyFourK; j > 1; j -= 2) {
indices.push(j, j - 1);
}
indices.push(0, 1);
var geometry = new Geometry({
attributes : {
position : new GeometryAttribute({
componentDatatype : ComponentDatatype.FLOAT,
componentsPerAttribute : 3,
values : positions
})
},
indices : indices,
primitiveType : PrimitiveType.LINES
});
var geometries = GeometryPipeline.fitToUnsignedShortIndices(geometry);
expect(geometries.length).toEqual(2);
expect(geometries[0].attributes.position.values.length).toEqual(positions.length - 12); // Four vertices are not copied
expect(geometries[0].indices.length).toEqual(indices.length - 4); // Two lines are not copied
expect(geometries[1].attributes.position.values.length).toEqual(9);
expect(geometries[1].indices.length).toEqual(4);
});
it('fitToUnsignedShortIndices creates two point geometries', function() {
var sixtyFourK = CesiumMath.SIXTY_FOUR_KILOBYTES;
var positions = [];
var indices = [];
for ( var i = 0; i < sixtyFourK + 1; ++i) {
positions.push(i, i, i);
indices.push(i);
}
var geometry = new Geometry({
attributes : {
position : new GeometryAttribute({
componentDatatype : ComponentDatatype.FLOAT,
componentsPerAttribute : 3,
values : positions
})
},
indices : indices,
primitiveType : PrimitiveType.POINTS
});
var geometries = GeometryPipeline.fitToUnsignedShortIndices(geometry);
expect(geometries.length).toEqual(2);
expect(geometries[0].attributes.position.values.length).toEqual(positions.length - 6); // Two vertices are not copied
expect(geometries[0].indices.length).toEqual(indices.length - 2); // Two points are not copied
expect(geometries[1].attributes.position.values.length).toEqual(6);
expect(geometries[1].indices.length).toEqual(2);
});
it('fitToUnsignedShortIndices throws without a geometry', function() {
expect(function() {
GeometryPipeline.fitToUnsignedShortIndices(undefined);
}).toThrowDeveloperError();
});
it('fitToUnsignedShortIndices throws without triangles, lines, or points', function() {
var geometry = new Geometry({
attributes : {
time : new GeometryAttribute({
componentDatatype : ComponentDatatype.FLOAT,
componentsPerAttribute : 1,
values : [10.0, 11.0, 12.0]
})
},
indices : [0, 1, 2],
primitiveType : PrimitiveType.TRIANGLE_STRIP
});
expect(function() {
return GeometryPipeline.fitToUnsignedShortIndices(geometry);
}).toThrowDeveloperError();
});
it('fitToUnsignedShortIndices throws with different numbers of attributes', function() {
var geometry = new Geometry({
attributes : {
time : new GeometryAttribute({
componentDatatype : ComponentDatatype.FLOAT,
componentsPerAttribute : 1,
values : [10.0]
}),
heat : new GeometryAttribute({
componentDatatype : ComponentDatatype.FLOAT,
componentsPerAttribute : 1,
values : [1.0, 2.0]
})
},
indices : [0, 0, 0],
primitiveType : PrimitiveType.TRIANGLES
});
expect(function() {
return GeometryPipeline.fitToUnsignedShortIndices(geometry);
}).toThrowDeveloperError();
});
it('projectTo2D', function() {
var p1 = new Cartesian3(100000, 200000, 300000);
var p2 = new Cartesian3(400000, 500000, 600000);
var geometry = {};
geometry.attributes = {};
geometry.attributes.position = {
componentDatatype : ComponentDatatype.DOUBLE,
componentsPerAttribute : 3,
values : [p1.x, p1.y, p1.z, p2.x, p2.y, p2.z]
};
geometry = GeometryPipeline.projectTo2D(geometry, 'position', 'position3D', 'position2D');
var ellipsoid = Ellipsoid.WGS84;
var projection = new GeographicProjection();
var projectedP1 = projection.project(ellipsoid.cartesianToCartographic(p1));
var projectedP2 = projection.project(ellipsoid.cartesianToCartographic(p2));
expect(geometry.attributes.position2D.values[0]).toEqual(projectedP1.x);
expect(geometry.attributes.position2D.values[1]).toEqual(projectedP1.y);
expect(geometry.attributes.position2D.values[2]).toEqual(projectedP1.z);
expect(geometry.attributes.position2D.values[3]).toEqual(projectedP2.x);
expect(geometry.attributes.position2D.values[4]).toEqual(projectedP2.y);
expect(geometry.attributes.position2D.values[5]).toEqual(projectedP2.z);
expect(geometry.attributes.position3D.values[0]).toEqual(p1.x);
expect(geometry.attributes.position3D.values[1]).toEqual(p1.y);
expect(geometry.attributes.position3D.values[2]).toEqual(p1.z);
expect(geometry.attributes.position3D.values[3]).toEqual(p2.x);
expect(geometry.attributes.position3D.values[4]).toEqual(p2.y);
expect(geometry.attributes.position3D.values[5]).toEqual(p2.z);
});
it('projectTo2D throws without a geometry', function() {
expect(function() {
GeometryPipeline.projectTo2D(undefined);
}).toThrowDeveloperError();
});
it('projectTo2D throws without attributeName', function() {
expect(function() {
GeometryPipeline.projectTo2D(new Geometry({
attributes : {
position : new GeometryAttribute({
componentDatatype : ComponentDatatype.DOUBLE,
componentsPerAttribute : 3,
values : [0.0, 0.0, 0.0]
})
},
primitiveType : PrimitiveType.POINTS
}));
}).toThrowDeveloperError();
});
it('projectTo2D throws without attributeName3D', function() {
expect(function() {
GeometryPipeline.projectTo2D(new Geometry({
attributes : {
position : new GeometryAttribute({
componentDatatype : ComponentDatatype.DOUBLE,
componentsPerAttribute : 3,
values : [0.0, 0.0, 0.0]
})
},
primitiveType : PrimitiveType.POINTS
}), 'position');
}).toThrowDeveloperError();
});
it('projectTo2D throws without attributeName2D', function() {
expect(function() {
GeometryPipeline.projectTo2D(new Geometry({
attributes : {
position : new GeometryAttribute({
componentDatatype : ComponentDatatype.DOUBLE,
componentsPerAttribute : 3,
values : [0.0, 0.0, 0.0]
})
},
primitiveType : PrimitiveType.POINTS
}), 'position', 'position3D');
}).toThrowDeveloperError();
});
it('projectTo2D throws without attribute', function() {
expect(function() {
GeometryPipeline.projectTo2D(new Geometry({
attributes : {
normal : new GeometryAttribute({
componentDatatype : ComponentDatatype.DOUBLE,
componentsPerAttribute : 3,
values : [0.0, 0.0, 0.0]
})
},
primitiveType : PrimitiveType.POINTS
}), 'position', 'position3D', 'position2D');
}).toThrowDeveloperError();
});
it('projectTo2D throws without ComponentDatatype.DOUBLE', function() {
expect(function() {
var geometry = new Geometry({
attributes : {
position : new GeometryAttribute({
componentDatatype : ComponentDatatype.UNSIGNED_SHORT,
componentsPerAttribute : 1,
values : [0.0]
})
}
});
GeometryPipeline.projectTo2D(geometry, 'position', 'position3D', 'position2D');
}).toThrowDeveloperError();
});
it('projectTo2D throws when trying to project a point close to the origin', function() {
var geometry = {};
geometry.attributes = {};
geometry.attributes.position = {
componentDatatype : ComponentDatatype.DOUBLE,
componentsPerAttribute : 3,
values : [100000.0, 200000.0, 300000.0, 0.0, 0.0, 0.0]
};
expect(function() {
return GeometryPipeline.projectTo2D(geometry, 'position', 'position3D', 'position2D');
}).toThrowDeveloperError();
});
it('encodeAttribute encodes positions', function() {
var c = new Cartesian3(-10000000.0, 0.0, 10000000.0);
var encoded = EncodedCartesian3.fromCartesian(c);
var geometry = new Geometry({
attributes : {
position : new GeometryAttribute({
componentDatatype : ComponentDatatype.DOUBLE,
componentsPerAttribute : 3,
values : [c.x, c.y, c.z]
})
},
primitiveType : PrimitiveType.POINTS
});
geometry = GeometryPipeline.encodeAttribute(geometry, 'position', 'positionHigh', 'positionLow');
expect(geometry.attributes.positionHigh).toBeDefined();
expect(geometry.attributes.positionHigh.values[0]).toEqual(encoded.high.x);
expect(geometry.attributes.positionHigh.values[1]).toEqual(encoded.high.y);
expect(geometry.attributes.positionHigh.values[2]).toEqual(encoded.high.z);
expect(geometry.attributes.positionLow).toBeDefined();
expect(geometry.attributes.positionLow.values[0]).toEqual(encoded.low.x);
expect(geometry.attributes.positionLow.values[1]).toEqual(encoded.low.y);
expect(geometry.attributes.positionLow.values[2]).toEqual(encoded.low.z);
expect(geometry.attributes.position).not.toBeDefined();
});
it('encodeAttribute throws without a geometry', function() {
expect(function() {
GeometryPipeline.encodeAttribute(undefined);
}).toThrowDeveloperError();
});
it('encodeAttribute throws without attributeName', function() {
expect(function() {
GeometryPipeline.encodeAttribute(new Geometry({
attributes : {
position : new GeometryAttribute({
componentDatatype : ComponentDatatype.DOUBLE,
componentsPerAttribute : 3,
values : [0.0, 0.0, 0.0]
})
},
primitiveType : PrimitiveType.POINTS
}));
}).toThrowDeveloperError();
});
it('encodeAttribute throws without attributeHighName', function() {
expect(function() {
GeometryPipeline.encodeAttribute(new Geometry({
attributes : {
position : new GeometryAttribute({
componentDatatype : ComponentDatatype.DOUBLE,
componentsPerAttribute : 3,
values : [0.0, 0.0, 0.0]
})
},
primitiveType : PrimitiveType.POINTS
}), 'position');
}).toThrowDeveloperError();
});
it('encodeAttribute throws without attributeLowName', function() {
expect(function() {
GeometryPipeline.encodeAttribute(new Geometry({
attributes : {
position : new GeometryAttribute({
componentDatatype : ComponentDatatype.DOUBLE,
componentsPerAttribute : 3,
values : [0.0, 0.0, 0.0]
})
},
primitiveType : PrimitiveType.POINTS
}), 'position', 'positionHigh');
}).toThrowDeveloperError();
});
it('encodeAttribute throws without attribute', function() {
expect(function() {
GeometryPipeline.encodeAttribute(new Geometry({
attributes : {
normal : new GeometryAttribute({
componentDatatype : ComponentDatatype.DOUBLE,
componentsPerAttribute : 3,
values : [0.0, 0.0, 0.0]
})
},
primitiveType : PrimitiveType.POINTS
}), 'position', 'positionHigh', 'positionLow');
}).toThrowDeveloperError();
});
it('encodeAttribute throws without ComponentDatatype.DOUBLE', function() {
expect(function() {
var geometry = new Geometry({
attributes : {
position : new GeometryAttribute({
componentDatatype : ComponentDatatype.UNSIGNED_SHORT,
componentsPerAttribute : 1,
values : [0.0]
})
}
});
GeometryPipeline.encodeAttribute(geometry, 'position', 'positionHigh', 'positionLow');
}).toThrowDeveloperError();
});
it('transformToWorldCoordinates', function() {
var instance = new GeometryInstance({
geometry : new Geometry({
attributes : {
position : new GeometryAttribute({
componentDatatype : ComponentDatatype.FLOAT,
componentsPerAttribute : 3,
values : [
0.0, 0.0, 0.0,
1.0, 0.0, 0.0,
0.0, 1.0, 0.0
]
}),
normal : new GeometryAttribute({
componentDatatype : ComponentDatatype.FLOAT,
componentsPerAttribute : 3,
values : [
0.0, 0.0, 1.0,
0.0, 0.0, 1.0,
0.0, 0.0, 1.0
]
})
},
indices : [0, 1, 2],
primitiveType : PrimitiveType.TRIANGLES,
boundingSphere : new BoundingSphere(new Cartesian3(0.5, 0.5, 0.0), 1.0)
}),
modelMatrix : new Matrix4(0.0, 0.0, 1.0, 0.0,
1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 0.0, 1.0)
});
var transformed = GeometryPipeline.transformToWorldCoordinates(instance);
var transformedPositions = [0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0];
var transformedNormals = [1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0];
expect(transformed.geometry.attributes.position.values).toEqual(transformedPositions);
expect(transformed.geometry.attributes.normal.values).toEqual(transformedNormals);
expect(transformed.geometry.boundingSphere).toEqual(new BoundingSphere(new Cartesian3(0.0, 0.5, 0.5), 1.0));
expect(transformed.modelMatrix).toEqual(Matrix4.IDENTITY);
});
it('transformToWorldCoordinates with non-uniform scale', function() {
var instance = new GeometryInstance({
geometry : new Geometry({
attributes : {
position : new GeometryAttribute({
componentDatatype : ComponentDatatype.FLOAT,
componentsPerAttribute : 3,
values : [
0.0, 0.0, 0.0,
1.0, 0.0, 0.0,
0.0, 1.0, 0.0
]
}),
normal : new GeometryAttribute({
componentDatatype : ComponentDatatype.FLOAT,
componentsPerAttribute : 3,
values : [
0.0, 0.0, 1.0,
0.0, 0.0, 1.0,
0.0, 0.0, 1.0
]
})
},
indices : [0, 1, 2],
primitiveType : PrimitiveType.TRIANGLES,
boundingSphere : new BoundingSphere(new Cartesian3(0.5, 0.5, 0.0), 1.0)
}),
modelMatrix : Matrix4.fromScale(new Cartesian3(1.0, 2.0, 4.0))
});
var transformed = GeometryPipeline.transformToWorldCoordinates(instance);
var transformedPositions = [0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 2.0, 0.0];
var transformedNormals = [0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0];
expect(transformed.geometry.attributes.position.values).toEqual(transformedPositions);
expect(transformed.geometry.attributes.normal.values).toEqual(transformedNormals);
expect(transformed.geometry.boundingSphere).toEqual(new BoundingSphere(new Cartesian3(0.5, 1.0, 0.0), 4.0));
expect(transformed.modelMatrix).toEqual(Matrix4.IDENTITY);
});
it('transformToWorldCoordinates does nothing when already in world coordinates', function() {
var instance = new GeometryInstance({
geometry : new Geometry({
attributes : {
position : new GeometryAttribute({
componentDatatype : ComponentDatatype.FLOAT,
componentsPerAttribute : 3,
values : [
0.0, 0.0, 0.0,
1.0, 0.0, 0.0,
0.0, 1.0, 0.0
]
}),
normal : new GeometryAttribute({
componentDatatype : ComponentDatatype.FLOAT,
componentsPerAttribute : 3,
values : [
0.0, 0.0, 1.0,
0.0, 0.0, 1.0,
0.0, 0.0, 1.0
]
})
},
indices : [0, 1, 2],
primitiveType : PrimitiveType.TRIANGLES,
boundingSphere : new BoundingSphere(new Cartesian3(0.5, 0.5, 0.0), 1.0)
}),
modelMatrix : Matrix4.IDENTITY
});
var transformed = GeometryPipeline.transformToWorldCoordinates(instance);
var transformedPositions = [0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0];
var transformedNormals = [0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0];
expect(transformed.geometry.attributes.position.values).toEqual(transformedPositions);
expect(transformed.geometry.attributes.normal.values).toEqual(transformedNormals);
expect(transformed.geometry.boundingSphere).toEqual(new BoundingSphere(new Cartesian3(0.5, 0.5, 0.0), 1.0));
expect(transformed.modelMatrix).toEqual(Matrix4.IDENTITY);
});
it('transformToWorldCoordinates throws without an instance', function() {
expect(function() {
GeometryPipeline.transformToWorldCoordinates();
}).toThrowDeveloperError();
});
it('combineInstances combines one geometry', function() {
var instance = new GeometryInstance({
geometry : new Geometry({
attributes : {
position : new GeometryAttribute({
componentDatatype : ComponentDatatype.FLOAT,
componentsPerAttribute : 3,
values : new Float32Array([0.0, 0.0, 0.0])
})
},
primitiveType : PrimitiveType.POINTS
})
});
var combined = GeometryPipeline.combineInstances([instance])[0];
expect(combined).toEqual(instance.geometry);
});
it('combineInstances combines several geometries without indicess', function() {
var instance = new GeometryInstance({
geometry : new Geometry({
attributes : {
position : new GeometryAttribute({
componentDatatype : ComponentDatatype.FLOAT,
componentsPerAttribute : 3,
values : [0.0, 0.0, 0.0]
})
},
primitiveType : PrimitiveType.POINTS
})
});
var anotherInstance = new GeometryInstance({
geometry : new Geometry({
attributes : {
position : new GeometryAttribute({
componentDatatype : ComponentDatatype.FLOAT,
componentsPerAttribute : 3,
values : [1.0, 1.0, 1.0]
})
},
primitiveType : PrimitiveType.POINTS
})
});
var combined = GeometryPipeline.combineInstances([instance, anotherInstance])[0];
expect(combined).toEqual(new Geometry({
attributes : {
position : new GeometryAttribute({
componentDatatype : ComponentDatatype.FLOAT,
componentsPerAttribute : 3,
values : new Float32Array([
0.0, 0.0, 0.0,
1.0, 1.0, 1.0
])
})
},
primitiveType : PrimitiveType.POINTS
}));
});
it('combineInstances combines several geometries with indicess', function() {
var instance = new GeometryInstance({
geometry : new Geometry({
attributes : {
position : new GeometryAttribute({
componentDatatype : ComponentDatatype.FLOAT,
componentsPerAttribute : 3,
values : [
0.0, 0.0, 0.0,
1.0, 1.0, 1.0,
2.0, 2.0, 2.0
]
}),
normal : new GeometryAttribute({
componentDatatype : ComponentDatatype.FLOAT,
componentsPerAttribute : 3,
values : [
0.0, 0.0, 0.0,
1.0, 1.0, 1.0,
2.0, 2.0, 2.0
]
})
},
indices : [0, 1, 2],
primitiveType : PrimitiveType.TRIANGLES
})
});
var anotherInstance = new GeometryInstance({
geometry : new Geometry({
attributes : {
position : new GeometryAttribute({
componentDatatype : ComponentDatatype.FLOAT,
componentsPerAttribute : 3,
values : [
3.0, 3.0, 3.0,
4.0, 4.0, 4.0,
5.0, 5.0, 5.0
]
})
},
indices : [0, 1, 2],
primitiveType : PrimitiveType.TRIANGLES
})
});
var combined = GeometryPipeline.combineInstances([instance, anotherInstance])[0];
expect(combined).toEqual(new Geometry({
attributes : {
position : new GeometryAttribute({
componentDatatype : ComponentDatatype.FLOAT,
componentsPerAttribute : 3,
values : new Float32Array([
0.0, 0.0, 0.0,
1.0, 1.0, 1.0,
2.0, 2.0, 2.0,
3.0, 3.0, 3.0,
4.0, 4.0, 4.0,
5.0, 5.0, 5.0
])
})
},
indices : new Uint16Array([0, 1, 2, 3, 4, 5]),
primitiveType : PrimitiveType.TRIANGLES
}));
});
it('combineInstances with geometry that is and is not split by the IDL', function() {
var instances = [
GeometryPipeline.splitLongitude(new GeometryInstance({
geometry : PolygonGeometry.createGeometry(PolygonGeometry.fromPositions({
positions : Cartesian3.fromDegreesArray([
179.0, 1.0,
179.0, -1.0,
-179.0, -1.0,
-179.0, 1.0
]),
vertexFormat : VertexFormat.POSITION_ONLY,
granularity : 2.0 * CesiumMath.RADIANS_PER_DEGREE
}))
})),
new GeometryInstance({
geometry : PolygonGeometry.createGeometry(PolygonGeometry.fromPositions({
positions : Cartesian3.fromDegreesArray([
-1.0, 1.0,
-1.0, -1.0,
1.0, -1.0,
1.0, 1.0
]),
vertexFormat : VertexFormat.POSITION_ONLY,
granularity : 2.0 * CesiumMath.RADIANS_PER_DEGREE
}))
})
];
var combinedInstances = GeometryPipeline.combineInstances(instances);
expect(combinedInstances.length).toEqual(3);
});
it('combineInstances combines bounding spheres', function() {
var instance = new GeometryInstance({
geometry : new Geometry({
attributes : {
position : new GeometryAttribute({
componentDatatype : ComponentDatatype.FLOAT,
componentsPerAttribute : 3,
values : [
0.0, 0.0, 0.0,
1.0, 0.0, 0.0,
0.0, 1.0, 0.0
]
})
},
indices : [0, 1, 2],
primitiveType : PrimitiveType.TRIANGLES,
boundingSphere : new BoundingSphere(new Cartesian3(0.5, 0.5, 0.0), 1.0)
})
});
var anotherInstance = new GeometryInstance({
geometry : new Geometry({
attributes : {
position : new GeometryAttribute({
componentDatatype : ComponentDatatype.FLOAT,
componentsPerAttribute : 3,
values : [
1.0, 0.0, 0.0,
2.0, 0.0, 0.0,
1.0, 1.0, 0.0
]
})
},
indices : [0, 1, 2],
primitiveType : PrimitiveType.TRIANGLES,
boundingSphere : new BoundingSphere(new Cartesian3(1.5, 0.5, 0.0), 1.0)
})
});
var combined = GeometryPipeline.combineInstances([instance, anotherInstance])[0];
var expected = BoundingSphere.union(instance.geometry.boundingSphere, anotherInstance.geometry.boundingSphere);
expect(combined.boundingSphere).toEqual(expected);
});
it('combineInstances throws without instances', function() {
expect(function() {
GeometryPipeline.combineInstances();
}).toThrowDeveloperError();
});
it('combineInstances throws when instances.length is zero', function() {
expect(function() {
GeometryPipeline.combineInstances([]);
}).toThrowDeveloperError();
});
it('combineInstances throws when instances.modelMatrix do not match', function() {
var instance0 = new GeometryInstance({
geometry : new Geometry({
attributes : {
position : new GeometryAttribute({
componentDatatype : ComponentDatatype.FLOAT,
componentsPerAttribute : 3,
values : [0.0, 0.0, 0.0]
})
},
primitiveType : PrimitiveType.POINTS
}),
modelMatrix : Matrix4.fromScale(new Cartesian3(1.0, 1.0, 1.0))
});
var instance1 = new GeometryInstance({
geometry : new Geometry({
attributes : {
position : new GeometryAttribute({
componentDatatype : ComponentDatatype.FLOAT,
componentsPerAttribute : 3,
values : [0.0, 0.0, 0.0]
})
},
primitiveType : PrimitiveType.POINTS
}),
modelMatrix : Matrix4.fromScale(new Cartesian3(2.0, 2.0, 2.0))
});
expect(function() {
GeometryPipeline.combineInstances([instance0, instance1]);
}).toThrowDeveloperError();
});
it('combineInstances throws when instance geometries do not all have or not have an indices', function() {
var instance0 = new GeometryInstance({
geometry : new Geometry({
attributes : {
position : new GeometryAttribute({
componentDatatype : ComponentDatatype.FLOAT,
componentsPerAttribute : 3,
values : [0.0, 0.0, 0.0]
})
},
indices : [0],
primitiveType : PrimitiveType.POINTS
})
});
var instance1 = new GeometryInstance({
geometry : new Geometry({
attributes : {
position : new GeometryAttribute({
componentDatatype : ComponentDatatype.FLOAT,
componentsPerAttribute : 3,
values : [0.0, 0.0, 0.0]
})
},
primitiveType : PrimitiveType.POINTS
})
});
expect(function() {
GeometryPipeline.combineInstances([instance0, instance1]);
}).toThrowDeveloperError();
});
it('combineInstances throws when instance geometries do not all have the same primitive type', function() {
var instance0 = new GeometryInstance({
geometry : new Geometry({
attributes : {
position : new GeometryAttribute({
componentDatatype : ComponentDatatype.FLOAT,
componentsPerAttribute : 3,
values : [0.0, 0.0, 0.0]
})
},
primitiveType : PrimitiveType.POINTS
})
});
var instance1 = new GeometryInstance({
geometry : new Geometry({
attributes : {
position : new GeometryAttribute({
componentDatatype : ComponentDatatype.FLOAT,
componentsPerAttribute : 3,
values : [0.0, 0.0, 0.0, 1.0, 0.0, 0.0]
})
},
primitiveType : PrimitiveType.LINES
})
});
expect(function() {
GeometryPipeline.combineInstances([instance0, instance1]);
}).toThrowDeveloperError();
});
it('computeNormal throws when geometry is undefined', function() {
expect(function() {
GeometryPipeline.computeNormal();
}).toThrowDeveloperError();
});
it('computeNormal throws when geometry.attributes.position is undefined', function() {
var geometry = new Geometry({
attributes: {},
primitiveType : PrimitiveType.TRIANGLES
});
expect(function() {
GeometryPipeline.computeNormal(geometry);
}).toThrowDeveloperError();
});
it('computeNormal throws when geometry.indices is undefined', function() {
var geometry = new Geometry({
attributes: {
position: new GeometryAttribute({
values: [0, 0, 0, 1, 0, 0, 0, 1, 0],
componentsPerAttribute: 3,
componentDatatype : ComponentDatatype.FLOAT
})
},
primitiveType : PrimitiveType.TRIANGLES
});
expect(function() {
GeometryPipeline.computeNormal(geometry);
}).toThrowDeveloperError();
});
it('computeNormal throws when geometry.indices.length is not a multiple of 3', function() {
var geometry = new Geometry({
attributes: {
position: new GeometryAttribute({
values: [0, 0, 0, 1, 0, 0, 0, 1],
componentsPerAttribute: 3,
componentDatatype : ComponentDatatype.FLOAT
})
},
primitiveType : PrimitiveType.TRIANGLES
});
expect(function() {
GeometryPipeline.computeNormal(geometry);
}).toThrowDeveloperError();
});
it('computeNormal throws when primitive type is not triangle', function() {
var geometry = new Geometry({
attributes: {
position: new GeometryAttribute({
values: [0, 0, 0, 1, 0, 0, 0, 1, 0],
componentsPerAttribute: 3,
componentDatatype : ComponentDatatype.FLOAT
})
},
indices : [0, 1, 2],
primitiveType: PrimitiveType.TRIANGLE_STRIP
});
expect(function() {
GeometryPipeline.computeNormal(geometry);
}).toThrowDeveloperError();
});
it('computeNormal computes normal for one triangle', function() {
var geometry = new Geometry({
attributes: {
position: new GeometryAttribute({
values: [0, 0, 0, 1, 0, 0, 0, 1, 0],
componentsPerAttribute: 3,
componentDatatype : ComponentDatatype.FLOAT
})
},
indices : [0, 1, 2],
primitiveType: PrimitiveType.TRIANGLES
});
geometry = GeometryPipeline.computeNormal(geometry);
expect(geometry.attributes.normal.values.length).toEqual(3*3);
expect(geometry.attributes.normal.values).toEqual([0, 0, 1, 0, 0, 1, 0, 0, 1]);
});
it('computeNormal computes normal for two triangles', function() {
var geometry = new Geometry({
attributes: {
position: new GeometryAttribute({
values: [0, 0, 0, 1, 0, 1, 1, 1, 1, 2, 0, 0],
componentsPerAttribute: 3,
componentDatatype : ComponentDatatype.FLOAT
})
},
indices : [0, 1, 2, 1, 3, 2],
primitiveType: PrimitiveType.TRIANGLES
});
geometry = GeometryPipeline.computeNormal(geometry);
var normals = geometry.attributes.normal.values;
expect(normals.length).toEqual(4*3);
var a = Cartesian3.normalize(new Cartesian3(-1, 0, 1), new Cartesian3());
expect(Cartesian3.fromArray(normals, 0)).toEqualEpsilon(a, CesiumMath.EPSILON7);
expect(Cartesian3.fromArray(normals, 3)).toEqualEpsilon(Cartesian3.UNIT_Z, CesiumMath.EPSILON7);
expect(Cartesian3.fromArray(normals, 6)).toEqualEpsilon(Cartesian3.UNIT_Z, CesiumMath.EPSILON7);
a = Cartesian3.normalize(new Cartesian3(1, 0, 1), new Cartesian3());
expect(Cartesian3.fromArray(normals, 9)).toEqualEpsilon(a, CesiumMath.EPSILON7);
});
it('computeNormal computes normal for six triangles', function() {
var geometry = new Geometry ({
attributes: {
position: new GeometryAttribute({
values: [0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0],
componentsPerAttribute: 3,
componentDatatype : ComponentDatatype.FLOAT
})
},
indices : [0, 1, 2, 3, 0, 2, 4, 0, 3, 4, 5, 0, 5, 6, 0, 6, 1, 0],
primitiveType: PrimitiveType.TRIANGLES
});
geometry = GeometryPipeline.computeNormal(geometry);
var normals = geometry.attributes.normal.values;
expect(normals.length).toEqual(7*3);
var a = Cartesian3.normalize(new Cartesian3(-1, -1, -1), new Cartesian3());
expect(Cartesian3.fromArray(normals, 0)).toEqualEpsilon(a, CesiumMath.EPSILON7);
a = Cartesian3.normalize(new Cartesian3(0, -1, -1), new Cartesian3());
expect(Cartesian3.fromArray(normals, 3)).toEqualEpsilon(a, CesiumMath.EPSILON7);
expect(Cartesian3.fromArray(normals, 6)).toEqualEpsilon(Cartesian3.negate(Cartesian3.UNIT_Y, new Cartesian3()), CesiumMath.EPSILON7);
a = Cartesian3.normalize(new Cartesian3(-1, -1, 0), new Cartesian3());
expect(Cartesian3.fromArray(normals, 9)).toEqualEpsilon(a, CesiumMath.EPSILON7);
expect(Cartesian3.fromArray(normals, 12)).toEqualEpsilon(Cartesian3.negate(Cartesian3.UNIT_X, new Cartesian3()), CesiumMath.EPSILON7);
a = Cartesian3.normalize(new Cartesian3(-1, 0, -1), new Cartesian3());
expect(Cartesian3.fromArray(normals, 15)).toEqualEpsilon(a, CesiumMath.EPSILON7);
expect(Cartesian3.fromArray(normals, 18)).toEqualEpsilon(Cartesian3.negate(Cartesian3.UNIT_Z, new Cartesian3()), CesiumMath.EPSILON7);
});
it('computeNormal computes normal of (0,0,1) for a degenerate triangle', function() {
var geometry = new Geometry({
attributes: {
position: new GeometryAttribute({
values: [0, 0, 0, 1, 0, 0],
componentsPerAttribute: 3,
componentDatatype : ComponentDatatype.FLOAT
})
},
indices : [0, 1, 0],
primitiveType: PrimitiveType.TRIANGLES
});
geometry = GeometryPipeline.computeNormal(geometry);
expect(geometry.attributes.normal.values.length).toEqual(2*3);
expect(geometry.attributes.normal.values).toEqual([0, 0, 1, 0, 0, 1]);
});
it('computeNormal takes first normal for two coplanar triangles with opposite winding orders', function() {
var geometry = new Geometry({
attributes: {
position: new GeometryAttribute({
values: [0, 0, 0, 1, 0, 1, 1, 1, 1],
componentsPerAttribute: 3,
componentDatatype : ComponentDatatype.FLOAT
})
},
indices : [0, 1, 2, 2, 1, 0],
primitiveType: PrimitiveType.TRIANGLES
});
geometry = GeometryPipeline.computeNormal(geometry);
var normals = geometry.attributes.normal.values;
expect(normals.length).toEqual(3*3);
var a = Cartesian3.normalize(new Cartesian3(-1, 0, 1), new Cartesian3());
expect(Cartesian3.fromArray(normals, 0)).toEqualEpsilon(a, CesiumMath.EPSILON7);
expect(Cartesian3.fromArray(normals, 3)).toEqualEpsilon(a, CesiumMath.EPSILON7);
expect(Cartesian3.fromArray(normals, 6)).toEqualEpsilon(a, CesiumMath.EPSILON7);
});
it('computeTangentAndBitangent throws when geometry is undefined', function() {
expect(function() {
GeometryPipeline.computeTangentAndBitangent();
}).toThrowDeveloperError();
});
it('computeTangentAndBitangent throws when position is undefined', function() {
var geometry = new Geometry({
attributes: {
normal: new GeometryAttribute({
values: [0, 0, 0, 1, 0, 0, 0, 1, 0],
componentsPerAttribute: 3,
componentDatatype : ComponentDatatype.FLOAT
}),
st: new GeometryAttribute({
values: [0, 0, 1, 1],
componentsPerAttribute: 2,
componentDatatype : ComponentDatatype.FLOAT
})
},
indices : [0, 1, 2],
primitiveType: PrimitiveType.TRIANGLE_STRIP
});
expect(function() {
GeometryPipeline.computeTangentAndBitangent(geometry);
}).toThrowDeveloperError();
});
it('computeTangentAndBitangent throws when normal is undefined', function() {
var geometry = new Geometry({
attributes: {
position: new GeometryAttribute({
values: [0, 0, 0, 1, 0, 0, 0, 1, 0],
componentsPerAttribute: 3,
componentDatatype : ComponentDatatype.FLOAT
}),
st: new GeometryAttribute({
values: [0, 0, 1, 1],
componentsPerAttribute: 2,
componentDatatype : ComponentDatatype.FLOAT
})
},
indices : [0, 1, 2],
primitiveType: PrimitiveType.TRIANGLE_STRIP
});
expect(function() {
GeometryPipeline.computeTangentAndBitangent(geometry);
}).toThrowDeveloperError();
});
it('computeTangentAndBitangent throws when st is undefined', function() {
var geometry = new Geometry({
attributes: {
position: new GeometryAttribute({
values: [0, 0, 0, 1, 0, 0, 0, 1, 0],
componentsPerAttribute: 3,
componentDatatype : ComponentDatatype.FLOAT
}),
normal: new GeometryAttribute({
values: [0, 0, 0, 1, 0, 0, 0, 1, 0],
componentsPerAttribute: 3,
componentDatatype : ComponentDatatype.FLOAT
})
},
indices : [0, 1, 2],
primitiveType: PrimitiveType.TRIANGLE_STRIP
});
expect(function() {
GeometryPipeline.computeTangentAndBitangent(geometry);
}).toThrowDeveloperError();
});
it('computeTangentAndBitangent throws when geometry.indices is undefined', function() {
var geometry = new Geometry({
attributes: {
position: new GeometryAttribute({
values: [0, 0, 0, 1, 0, 0, 0, 1, 0],
componentsPerAttribute: 3,
componentDatatype : ComponentDatatype.FLOAT
}),
normal: new GeometryAttribute({
values: [0, 0, 0, 1, 0, 0, 0, 1, 0],
componentsPerAttribute: 3,
componentDatatype : ComponentDatatype.FLOAT
}),
st: new GeometryAttribute({
values: [0, 0, 1, 1],
componentsPerAttribute: 2,
componentDatatype : ComponentDatatype.FLOAT
})
},
primitiveType : PrimitiveType.POINTS
});
expect(function() {
GeometryPipeline.computeTangentAndBitangent(geometry);
}).toThrowDeveloperError();
});
it('computeTangentAndBitangent throws when indices is not a multiple of 3', function() {
var geometry = new Geometry({
attributes: {
position: new GeometryAttribute({
values: [0, 0, 0, 1, 0, 0, 0, 1, 0],
componentsPerAttribute: 3,
componentDatatype : ComponentDatatype.FLOAT
}),
normal: new GeometryAttribute({
values: [0, 0, 0, 1, 0, 0, 0, 1, 0],
componentsPerAttribute: 3,
componentDatatype : ComponentDatatype.FLOAT
}),
st: new GeometryAttribute({
values: [0, 0, 1, 1],
componentsPerAttribute: 2,
componentDatatype : ComponentDatatype.FLOAT
})
},
indices : [0, 1, 2, 3, 4],
primitiveType: PrimitiveType.TRIANGLES
});
expect(function() {
GeometryPipeline.computeTangentAndBitangent(geometry);
}).toThrowDeveloperError();
});
it('computeTangentAndBitangent throws when primitive type is not triangle', function() {
var geometry = new Geometry({
attributes: {
position: new GeometryAttribute({
values: [0, 0, 0, 1, 0, 0, 0, 1, 0],
componentsPerAttribute: 3,
componentDatatype : ComponentDatatype.FLOAT
}),
normal: new GeometryAttribute({
values: [0, 0, 0, 1, 0, 0, 0, 1, 0],
componentsPerAttribute: 3,
componentDatatype : ComponentDatatype.FLOAT
}),
st: new GeometryAttribute({
values: [0, 0, 1, 1],
componentsPerAttribute: 2,
componentDatatype : ComponentDatatype.FLOAT
})
},
indices : [0, 1, 2],
primitiveType: PrimitiveType.TRIANGLE_STRIP
});
expect(function() {
GeometryPipeline.computeTangentAndBitangent(geometry);
}).toThrowDeveloperError();
});
it('computeTangentAndBitangent computes tangent and bitangent for one triangle', function() {
var geometry = new Geometry({
attributes: {
position: new GeometryAttribute({
values: [0, 0, 0, 1, 0, 0, 0, 1, 0],
componentsPerAttribute: 3,
componentDatatype : ComponentDatatype.FLOAT
}),
st: new GeometryAttribute({
values: [0, 0, 1, 0, 0, 1],
componentsPerAttribute: 2,
componentDatatype : ComponentDatatype.FLOAT
})
},
indices : [0, 1, 2],
primitiveType: PrimitiveType.TRIANGLES
});
geometry = GeometryPipeline.computeNormal(geometry);
geometry = GeometryPipeline.computeTangentAndBitangent(geometry);
expect(geometry.attributes.tangent.values).toEqual([1, 0, 0, 1, 0, 0, 1, 0, 0]);
expect(geometry.attributes.bitangent.values).toEqual([0, 1, 0, 0, 1, 0, 0, 1, 0]);
});
it('computeTangentAndBitangent computes tangent and bitangent for two triangles', function() {
var geometry = new Geometry({
attributes: {
position: new GeometryAttribute({
values: [0, 0, 0, 1, 0, 1, 1, 1, 1, 2, 0, 0],
componentsPerAttribute: 3,
componentDatatype : ComponentDatatype.FLOAT
}),
st: new GeometryAttribute({
values: [0, 0, 1, 0, 1, 1, 0, 1],
componentsPerAttribute: 2,
componentDatatype : ComponentDatatype.FLOAT
})
},
indices : [0, 1, 2, 1, 3, 2],
primitiveType: PrimitiveType.TRIANGLES
});
geometry = GeometryPipeline.computeNormal(geometry);
geometry = GeometryPipeline.computeTangentAndBitangent(geometry);
expect(geometry.attributes.tangent.values).toEqualEpsilon([0.7071067811865475, 0, 0.7071067811865475,
0, 1, 0,
0, 1, 0,
-0.5773502691896258, 0.5773502691896258, 0.5773502691896258], CesiumMath.EPSILON7);
expect(geometry.attributes.bitangent.values).toEqualEpsilon([0, 1, 0,
-1, 0, 0,
-1, 0, 0,
-0.4082482904638631, -0.8164965809277261, 0.4082482904638631], CesiumMath.EPSILON7);
});
it ('computeTangentAndBitangent computes tangent and bitangent for BoxGeometry', function() {
var geometry = BoxGeometry.createGeometry(new BoxGeometry({
vertexFormat : new VertexFormat({
position : true,
normal : true,
st : true
}),
maximum : new Cartesian3(250000.0, 250000.0, 250000.0),
minimum : new Cartesian3(-250000.0, -250000.0, -250000.0)
}));
geometry = GeometryPipeline.computeTangentAndBitangent(geometry);
var actualTangents = geometry.attributes.tangent.values;
var actualBitangents = geometry.attributes.bitangent.values;
var expectedGeometry = BoxGeometry.createGeometry(new BoxGeometry({
vertexFormat: VertexFormat.ALL,
maximum : new Cartesian3(250000.0, 250000.0, 250000.0),
minimum : new Cartesian3(-250000.0, -250000.0, -250000.0)
}));
var expectedTangents = expectedGeometry.attributes.tangent.values;
var expectedBitangents = expectedGeometry.attributes.bitangent.values;
expect(actualTangents.length).toEqual(expectedTangents.length);
expect(actualBitangents.length).toEqual(expectedBitangents.length);
for (var i = 0; i < actualTangents.length; i += 3) {
var actual = Cartesian3.fromArray(actualTangents, i);
var expected = Cartesian3.fromArray(expectedTangents, i);
expect(actual).toEqualEpsilon(expected, CesiumMath.EPSILON1);
actual = Cartesian3.fromArray(actualBitangents, i);
expected = Cartesian3.fromArray(expectedBitangents, i);
expect(actual).toEqualEpsilon(expected, CesiumMath.EPSILON1);
}
});
it('compressVertices throws without geometry', function() {
expect(function() {
return GeometryPipeline.compressVertices();
}).toThrowDeveloperError();
});
it('compressVertices on geometry without normals or texture coordinates does nothing', function() {
var geometry = BoxGeometry.createGeometry(new BoxGeometry({
vertexFormat : new VertexFormat({
position : true
}),
maximum : new Cartesian3(250000.0, 250000.0, 250000.0),
minimum : new Cartesian3(-250000.0, -250000.0, -250000.0)
}));
expect(geometry.attributes.normal).not.toBeDefined();
geometry = GeometryPipeline.compressVertices(geometry);
expect(geometry.attributes.normal).not.toBeDefined();
});
it('compressVertices compresses normals', function() {
var geometry = BoxGeometry.createGeometry(new BoxGeometry({
vertexFormat : new VertexFormat({
position : true,
normal : true
}),
maximum : new Cartesian3(250000.0, 250000.0, 250000.0),
minimum : new Cartesian3(-250000.0, -250000.0, -250000.0)
}));
expect(geometry.attributes.normal).toBeDefined();
var originalNormals = arraySlice(geometry.attributes.normal.values);
geometry = GeometryPipeline.compressVertices(geometry);
expect(geometry.attributes.compressedAttributes).toBeDefined();
var normals = geometry.attributes.compressedAttributes.values;
expect(normals.length).toEqual(originalNormals.length / 3);
for (var i = 0; i < normals.length; ++i) {
expect(AttributeCompression.octDecodeFloat(normals[i], new Cartesian3())).toEqualEpsilon(Cartesian3.fromArray(originalNormals, i * 3), CesiumMath.EPSILON2);
}
});
it('compressVertices compresses texture coordinates', function() {
var geometry = BoxGeometry.createGeometry(new BoxGeometry({
vertexFormat : new VertexFormat({
position : true,
st : true
}),
maximum : new Cartesian3(250000.0, 250000.0, 250000.0),
minimum : new Cartesian3(-250000.0, -250000.0, -250000.0)
}));
expect(geometry.attributes.st).toBeDefined();
var originalST = arraySlice(geometry.attributes.st.values);
geometry = GeometryPipeline.compressVertices(geometry);
expect(geometry.attributes.st).not.toBeDefined();
expect(geometry.attributes.compressedAttributes).toBeDefined();
var st = geometry.attributes.compressedAttributes.values;
expect(st.length).toEqual(originalST.length / 2);
for (var i = 0; i < st.length; ++i) {
var temp = st[i] / 4096.0;
var stx = Math.floor(temp) / 4096.0;
var sty = temp - Math.floor(temp);
var texCoord = new Cartesian2(stx, sty);
expect(texCoord).toEqualEpsilon(Cartesian2.fromArray(originalST, i * 2, new Cartesian2()), CesiumMath.EPSILON2);
}
});
it('compressVertices packs compressed normals with texture coordinates', function() {
var geometry = BoxGeometry.createGeometry(new BoxGeometry({
vertexFormat : new VertexFormat({
position : true,
normal : true,
st : true
}),
maximum : new Cartesian3(250000.0, 250000.0, 250000.0),
minimum : new Cartesian3(-250000.0, -250000.0, -250000.0)
}));
expect(geometry.attributes.normal).toBeDefined();
expect(geometry.attributes.st).toBeDefined();
var originalNormals = arraySlice(geometry.attributes.normal.values);
var originalST = arraySlice(geometry.attributes.st.values);
geometry = GeometryPipeline.compressVertices(geometry);
expect(geometry.attributes.normal).not.toBeDefined();
expect(geometry.attributes.st).not.toBeDefined();
expect(geometry.attributes.compressedAttributes).toBeDefined();
var stNormal = geometry.attributes.compressedAttributes.values;
expect(stNormal.length).toEqual(originalST.length);
for (var i = 0; i < stNormal.length; i += 2) {
expect(AttributeCompression.decompressTextureCoordinates(stNormal[i], new Cartesian2())).toEqualEpsilon(Cartesian2.fromArray(originalST, i, new Cartesian2()), CesiumMath.EPSILON2);
expect(AttributeCompression.octDecodeFloat(stNormal[i + 1], new Cartesian3())).toEqualEpsilon(Cartesian3.fromArray(originalNormals, i / 2 * 3), CesiumMath.EPSILON2);
}
});
it('compressVertices packs compressed tangents and bitangents', function() {
var geometry = BoxGeometry.createGeometry(new BoxGeometry({
vertexFormat : new VertexFormat({
position : true,
normal : true,
tangent : true,
bitangent : true
}),
maximum : new Cartesian3(250000.0, 250000.0, 250000.0),
minimum : new Cartesian3(-250000.0, -250000.0, -250000.0)
}));
expect(geometry.attributes.normal).toBeDefined();
expect(geometry.attributes.tangent).toBeDefined();
expect(geometry.attributes.bitangent).toBeDefined();
var originalNormals = arraySlice(geometry.attributes.normal.values);
var originalTangents = arraySlice(geometry.attributes.tangent.values);
var originalBitangents = arraySlice(geometry.attributes.bitangent.values);
geometry = GeometryPipeline.compressVertices(geometry);
expect(geometry.attributes.tangent).not.toBeDefined();
expect(geometry.attributes.bitangent).not.toBeDefined();
expect(geometry.attributes.compressedAttributes).toBeDefined();
var compressedNormals = geometry.attributes.compressedAttributes.values;
expect(compressedNormals.length).toEqual(originalNormals.length / 3 * 2);
var normal = new Cartesian3();
var tangent = new Cartesian3();
var bitangent = new Cartesian3();
for (var i = 0; i < compressedNormals.length; i += 2) {
var compressed = Cartesian2.fromArray(compressedNormals, i, new Cartesian2());
AttributeCompression.octUnpack(compressed, normal, tangent, bitangent);
expect(normal).toEqualEpsilon(Cartesian3.fromArray(originalNormals, i / 2 * 3), CesiumMath.EPSILON2);
expect(tangent).toEqualEpsilon(Cartesian3.fromArray(originalTangents, i / 2 * 3), CesiumMath.EPSILON2);
expect(bitangent).toEqualEpsilon(Cartesian3.fromArray(originalBitangents, i / 2 * 3), CesiumMath.EPSILON2);
}
});
it('splitLongitude does nothing for geometry not split by the IDL', function() {
var instance = new GeometryInstance({
geometry : PolygonGeometry.createGeometry(PolygonGeometry.fromPositions({
positions : Cartesian3.fromDegreesArray([
-1.0, 1.0,
-1.0, -1.0,
1.0, -1.0,
1.0, 1.0
]),
vertexFormat : VertexFormat.POSITION_ONLY,
granularity : 2.0 * CesiumMath.RADIANS_PER_DEGREE
}))
});
var splitInstance = GeometryPipeline.splitLongitude(instance);
expect(splitInstance).toBe(instance);
});
it('splitLongitude interpolates custom attributes for geometry split by the IDL', function() {
var p0 = Cartesian3.fromDegrees(-179.0, 0.0);
var p1 = Cartesian3.fromDegrees(179.0, 0.0);
var p2 = Cartesian3.fromDegrees(-179.0, 1.0);
var positions = new Float64Array([
p0.x, p0.y, p0.z,
p1.x, p1.y, p1.z,
p2.x, p2.y, p2.z
]);
var vec4s = new Uint8Array([
0, 0, 0, 0,
0, 0, 0, 255,
0, 0, 0, 0
]);
var vec3s = new Uint8Array([
0, 0, 0,
0, 0, 255,
0, 0, 0
]);
var vec2s = new Uint8Array([
0, 0,
0, 255,
0, 0
]);
var scalars = new Uint8Array([0, 255, 0]);
var instance = new GeometryInstance({
geometry : new Geometry({
attributes : {
position : new GeometryAttribute({
componentDatatype : ComponentDatatype.DOUBLE,
componentsPerAttribute : 3,
values : positions
}),
vec4s: new GeometryAttribute({
componentDatatype: ComponentDatatype.UNSIGNED_BYTE,
componentsPerAttribute: 4,
values: vec4s
}),
vec3s: new GeometryAttribute({
componentDatatype: ComponentDatatype.UNSIGNED_BYTE,
componentsPerAttribute: 3,
values: vec3s
}),
vec2s: new GeometryAttribute({
componentDatatype: ComponentDatatype.UNSIGNED_BYTE,
componentsPerAttribute: 2,
values: vec2s
}),
scalars: new GeometryAttribute({
componentDatatype: ComponentDatatype.UNSIGNED_BYTE,
componentsPerAttribute: 1,
values: scalars
})
},
indices : new Uint16Array([0, 1, 2]),
primitiveType : PrimitiveType.TRIANGLES,
boundingSphere : BoundingSphere.fromVertices(positions)
})
});
var splitInstance = GeometryPipeline.splitLongitude(instance);
var eastHemisphereGeometry = splitInstance.eastHemisphereGeometry;
expect(eastHemisphereGeometry.indices.length).toEqual(3);
var newVec4s = eastHemisphereGeometry.attributes.vec4s.values;
var newVec3s = eastHemisphereGeometry.attributes.vec3s.values;
var newVec2s = eastHemisphereGeometry.attributes.vec2s.values;
var newScalars = eastHemisphereGeometry.attributes.scalars.values;
var i;
var index;
// Expect eastern hemisphere vertices to all be 255 or 127 at the end of the value
expect(Array.prototype.indexOf.call(newScalars, 127)).not.toBe(-1);
expect(Array.prototype.indexOf.call(newVec4s, 127)).not.toBe(-1);
expect(Array.prototype.indexOf.call(newVec3s, 127)).not.toBe(-1);
expect(Array.prototype.indexOf.call(newVec2s, 127)).not.toBe(-1);
for (i = 0; i < 3; i++) {
expect(newScalars[i] === 255 || newScalars[i] === 127).toBe(true);
index = i * 2;
expect(newVec2s[index]).toBe(0);
expect(newVec2s[index + 1] === 255 || newVec2s[index + 1] === 127).toBe(true);
index = i * 3;
expect(newVec3s[index]).toBe(0);
expect(newVec3s[index + 1]).toBe(0);
expect(newVec3s[index + 2] === 255 || newVec3s[index + 2] === 127).toBe(true);
index = i * 4;
expect(newVec4s[index]).toBe(0);
expect(newVec4s[index + 1]).toBe(0);
expect(newVec4s[index + 2]).toBe(0);
expect(newVec4s[index + 3] === 255 || newVec4s[index + 3] === 127).toBe(true);
}
var westHemisphereGeometry = splitInstance.westHemisphereGeometry;
expect(westHemisphereGeometry.indices.length).toEqual(6);
newVec4s = westHemisphereGeometry.attributes.vec4s.values;
newVec3s = westHemisphereGeometry.attributes.vec3s.values;
newVec2s = westHemisphereGeometry.attributes.vec2s.values;
newScalars = westHemisphereGeometry.attributes.scalars.values;
// Expect eastern hemisphere vertices to all be 0 or 127 at the end of the value
expect(Array.prototype.indexOf.call(newScalars, 127)).not.toBe(-1);
expect(Array.prototype.indexOf.call(newVec4s, 127)).not.toBe(-1);
expect(Array.prototype.indexOf.call(newVec3s, 127)).not.toBe(-1);
expect(Array.prototype.indexOf.call(newVec2s, 127)).not.toBe(-1);
for (i = 0; i < 4; i++) {
expect(newScalars[i] === 0 || newScalars[i] === 127).toBe(true);
index = i * 2;
expect(newVec2s[index]).toBe(0);
expect(newVec2s[index + 1] === 0 || newVec2s[index + 1] === 127).toBe(true);
index = i * 3;
expect(newVec3s[index]).toBe(0);
expect(newVec3s[index + 1]).toBe(0);
expect(newVec3s[index + 2] === 0 || newVec3s[index + 2] === 127).toBe(true);
index = i * 4;
expect(newVec4s[index]).toBe(0);
expect(newVec4s[index + 1]).toBe(0);
expect(newVec4s[index + 2]).toBe(0);
expect(newVec4s[index + 3] === 0 || newVec4s[index + 3] === 127).toBe(true);
}
});
it('splitLongitude provides indices for an un-indexed triangle list', function() {
var instance = new GeometryInstance({
geometry : new Geometry({
attributes : {
position : new GeometryAttribute({
componentDatatype : ComponentDatatype.DOUBLE,
componentsPerAttribute : 3,
values : new Float64Array([
0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0,
8.0, 7.0, 6.0, 5.0, 4.0, 3.0, 2.0, 1.0, 0.0])
})
},
primitiveType : PrimitiveType.TRIANGLES
})
});
GeometryPipeline.splitLongitude(instance);
expect(instance.geometry.indices).toEqual([0, 1, 2, 3, 4, 5]);
});
it('splitLongitude returns unchanged geometry if indices are already defined for an un-indexed triangle list', function() {
var instance = new GeometryInstance({
geometry : new Geometry({
attributes : {
position : new GeometryAttribute({
componentDatatype : ComponentDatatype.DOUBLE,
componentsPerAttribute : 3,
values : new Float64Array([
0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0,
8.0, 7.0, 6.0, 5.0, 4.0, 3.0, 2.0, 1.0, 0.0])
})
},
primitiveType : PrimitiveType.TRIANGLES,
indices : new Uint16Array([0, 1, 2, 3, 4, 5])
})
});
GeometryPipeline.splitLongitude(instance);
expect(instance.geometry.indices).toEqual([0, 1, 2, 3, 4, 5]);
});
it('splitLongitude throws when primitive type is TRIANGLES and number of vertices is less than 3', function() {
var instance = new GeometryInstance({
geometry : new Geometry({
attributes : {
position : new GeometryAttribute({
componentDatatype : ComponentDatatype.DOUBLE,
componentsPerAttribute : 3,
values : new Float64Array([0.0, 1.0, 2.0])
})
},
primitiveType : PrimitiveType.TRIANGLES
})
});
expect(function() {
GeometryPipeline.splitLongitude(instance);
}).toThrowDeveloperError();
});
it('splitLongitude throws when primitive type is TRIANGLES and number of vertices is not a multiple of 3', function() {
var instance = new GeometryInstance({
geometry : new Geometry({
attributes : {
position : new GeometryAttribute({
componentDatatype : ComponentDatatype.DOUBLE,
componentsPerAttribute : 3,
values : new Float64Array([
0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0,
8.0, 7.0, 6.0, 5.0, 4.0, 3.0, 2.0, 1.0])
})
},
primitiveType : PrimitiveType.TRIANGLES
})
});
expect(function() {
GeometryPipeline.splitLongitude(instance);
}).toThrowDeveloperError();
});
it('splitLongitude creates indexed triangles for a triangle fan', function() {
var instance = new GeometryInstance({
geometry : new Geometry({
attributes : {
position : new GeometryAttribute({
componentDatatype : ComponentDatatype.DOUBLE,
componentsPerAttribute : 3,
values : new Float64Array([0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 8.0, 7.0, 6.0])
})
},
primitiveType : PrimitiveType.TRIANGLE_FAN
})
});
GeometryPipeline.splitLongitude(instance);
expect(instance.geometry.primitiveType).toEqual(PrimitiveType.TRIANGLES);
expect(instance.geometry.indices).toEqual([0, 1, 2, 2, 1, 3]);
});
it('splitLongitude throws when primitive type is TRIANGLE_FAN and number of vertices is less than 3', function() {
var instance = new GeometryInstance({
geometry : new Geometry({
attributes : {
position : new GeometryAttribute({
componentDatatype : ComponentDatatype.DOUBLE,
componentsPerAttribute : 3,
values : new Float64Array([0.0, 1.0, 2.0])
})
},
primitiveType : PrimitiveType.TRIANGLE_FAN
})
});
expect(function() {
GeometryPipeline.splitLongitude(instance);
}).toThrowDeveloperError();
});
it('splitLongitude creates indexd triangles for triangle strips', function() {
var instance = new GeometryInstance({
geometry : new Geometry({
attributes : {
position : new GeometryAttribute({
componentDatatype : ComponentDatatype.DOUBLE,
componentsPerAttribute : 3,
values : new Float64Array([0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0,
8.0, 7.0, 6.0, 5.0, 4.0, 3.0, 2.0, 1.0, 0.0])
})
},
primitiveType : PrimitiveType.TRIANGLE_STRIP
})
});
GeometryPipeline.splitLongitude(instance);
expect(instance.geometry.primitiveType).toEqual(PrimitiveType.TRIANGLES);
expect(instance.geometry.indices).toEqual([0, 1, 2, 0, 2, 3, 3, 2, 4, 3, 4, 5]);
});
it('splitLongitude throws when the primitive type is TRIANGLE_STRIP and number of vertices is less than 3', function() {
var instance = new GeometryInstance({
geometry : new Geometry({
attributes : {
position : new GeometryAttribute({
componentDatatype : ComponentDatatype.DOUBLE,
componentsPerAttribute : 3,
values : new Float64Array([0.0, 1.0, 2.0])
})
},
primitiveType : PrimitiveType.TRIANGLE_STRIP
})
});
expect(function() {
GeometryPipeline.splitLongitude(instance);
}).toThrowDeveloperError();
});
it('splitLongitude creates indexed lines', function() {
var instance = new GeometryInstance({
geometry : new Geometry({
attributes : {
position : new GeometryAttribute({
componentDatatype : ComponentDatatype.DOUBLE,
componentsPerAttribute : 3,
values : new Float64Array([0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 8.0, 7.0, 6.0])
})
},
primitiveType : PrimitiveType.LINES
})
});
GeometryPipeline.splitLongitude(instance);
expect(instance.geometry.indices).toEqual([0, 1, 2, 3]);
});
it('splitLongitude returns lines unchanged if indices are provided', function() {
var instance = new GeometryInstance({
geometry : new Geometry({
attributes : {
position : new GeometryAttribute({
componentDatatype : ComponentDatatype.DOUBLE,
componentsPerAttribute : 3,
values : new Float64Array([0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 8.0, 7.0, 6.0])
})
},
primitiveType : PrimitiveType.LINES,
indices : new Uint16Array([0, 1, 2, 3])
})
});
GeometryPipeline.splitLongitude(instance);
expect(instance.geometry.indices).toEqual([0, 1, 2, 3]);
});
it('splitLongitude throws when primitive type is LINES and number of vertices is less than 2', function() {
var instance = new GeometryInstance({
geometry : new Geometry({
attributes : {
position : new GeometryAttribute({
componentDatatype : ComponentDatatype.DOUBLE,
componentsPerAttribute : 3,
values : new Float64Array([0.0, 1.0, 2.0])
})
},
primitiveType : PrimitiveType.LINES
})
});
expect(function() {
GeometryPipeline.splitLongitude(instance);
}).toThrowDeveloperError();
});
it('splitLongitude throws when primitive type is LINES and number of vertices is not a multiple 2', function() {
var instance = new GeometryInstance({
geometry : new Geometry({
attributes : {
position : new GeometryAttribute({
componentDatatype : ComponentDatatype.DOUBLE,
componentsPerAttribute : 3,
values : new Float64Array([0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0])
})
},
primitiveType : PrimitiveType.LINES
})
});
expect(function() {
GeometryPipeline.splitLongitude(instance);
}).toThrowDeveloperError();
});
it('splitLongitude creates indexed lines from line strip', function() {
var instance = new GeometryInstance({
geometry : new Geometry({
attributes : {
position : new GeometryAttribute({
componentDatatype : ComponentDatatype.DOUBLE,
componentsPerAttribute : 3,
values : new Float64Array([0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 8.0, 7.0, 6.0])
})
},
primitiveType : PrimitiveType.LINE_STRIP
})
});
GeometryPipeline.splitLongitude(instance);
expect(instance.geometry.primitiveType).toEqual(PrimitiveType.LINES);
expect(instance.geometry.indices).toEqual([0, 1, 1, 2, 2, 3]);
});
it('splitLongitude throws when primitive type is LINE_STRIP and number of vertices is less than 2', function() {
var instance = new GeometryInstance({
geometry : new Geometry({
attributes : {
position : new GeometryAttribute({
componentDatatype : ComponentDatatype.DOUBLE,
componentsPerAttribute : 3,
values : new Float64Array([0.0, 1.0, 2.0])
})
},
primitiveType : PrimitiveType.LINE_STRIP
})
});
expect(function() {
GeometryPipeline.splitLongitude(instance);
}).toThrowDeveloperError();
});
it('splitLongitude creates indexed lines from line loops', function() {
var instance = new GeometryInstance({
geometry : new Geometry({
attributes : {
position : new GeometryAttribute({
componentDatatype : ComponentDatatype.DOUBLE,
componentsPerAttribute : 3,
values : new Float64Array([0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 8.0, 7.0, 6.0])
})
},
primitiveType : PrimitiveType.LINE_LOOP
})
});
GeometryPipeline.splitLongitude(instance);
expect(instance.geometry.primitiveType).toEqual(PrimitiveType.LINES);
expect(instance.geometry.indices).toEqual([0, 1, 1, 2, 2, 3, 3, 0]);
});
it('splitLongitude throws when the primitive type is LINE_LOOP and number of vertices is less than 2', function() {
var instance = new GeometryInstance({
geometry : new Geometry({
attributes : {
position : new GeometryAttribute({
componentDatatype : ComponentDatatype.DOUBLE,
componentsPerAttribute : 3,
values : new Float64Array([0.0, 1.0, 2.0])
})
},
primitiveType : PrimitiveType.LINE_LOOP
})
});
expect(function() {
GeometryPipeline.splitLongitude(instance);
}).toThrowDeveloperError();
});
it('splitLongitude subdivides triangle crossing the international date line, p0 behind', function() {
var instance = new GeometryInstance({
geometry : new Geometry({
attributes : {
position : new GeometryAttribute({
componentDatatype : ComponentDatatype.DOUBLE,
componentsPerAttribute : 3,
values : new Float64Array([-1.0, -1.0, 0.0, -1.0, 1.0, 2.0, -1.0, 2.0, 2.0])
})
},
indices : new Uint16Array([0, 1, 2]),
primitiveType : PrimitiveType.TRIANGLES
})
});
GeometryPipeline.splitLongitude(instance);
expect(instance.geometry).not.toBeDefined();
expect(instance.westHemisphereGeometry).toBeDefined();
expect(instance.westHemisphereGeometry.indices).toBeDefined();
expect(instance.westHemisphereGeometry.indices.length).toEqual(3);
expect(instance.westHemisphereGeometry.attributes.position).toBeDefined();
expect(instance.westHemisphereGeometry.attributes.position.values.length).toEqual(3 * 3);
expect(instance.eastHemisphereGeometry).toBeDefined();
expect(instance.eastHemisphereGeometry.indices).toBeDefined();
expect(instance.eastHemisphereGeometry.indices.length).toEqual(6);
expect(instance.eastHemisphereGeometry.attributes.position).toBeDefined();
expect(instance.eastHemisphereGeometry.attributes.position.values.length).toEqual(5 * 3);
});
it('splitLongitude subdivides triangle crossing the international date line, p1 behind', function() {
var instance = new GeometryInstance({
geometry : new Geometry({
attributes : {
position : new GeometryAttribute({
componentDatatype : ComponentDatatype.DOUBLE,
componentsPerAttribute : 3,
values : new Float64Array([-1.0, 1.0, 2.0, -1.0, -1.0, 0.0, -1.0, 2.0, 2.0])
})
},
indices : new Uint16Array([0, 1, 2]),
primitiveType : PrimitiveType.TRIANGLES
})
});
GeometryPipeline.splitLongitude(instance);
expect(instance.geometry).not.toBeDefined();
expect(instance.westHemisphereGeometry).toBeDefined();
expect(instance.westHemisphereGeometry.indices).toBeDefined();
expect(instance.westHemisphereGeometry.indices.length).toEqual(3);
expect(instance.westHemisphereGeometry.attributes.position).toBeDefined();
expect(instance.westHemisphereGeometry.attributes.position.values.length).toEqual(3 * 3);
expect(instance.eastHemisphereGeometry).toBeDefined();
expect(instance.eastHemisphereGeometry.indices).toBeDefined();
expect(instance.eastHemisphereGeometry.indices.length).toEqual(6);
expect(instance.eastHemisphereGeometry.attributes.position).toBeDefined();
expect(instance.eastHemisphereGeometry.attributes.position.values.length).toEqual(5 * 3);
});
it('splitLongitude subdivides triangle crossing the international date line, p2 behind', function() {
var instance = new GeometryInstance({
geometry : new Geometry({
attributes : {
position : new GeometryAttribute({
componentDatatype : ComponentDatatype.DOUBLE,
componentsPerAttribute : 3,
values : new Float64Array([-1.0, 1.0, 2.0, -1.0, 2.0, 2.0, -1.0, -1.0, 0.0])
})
},
indices : new Uint16Array([0, 1, 2]),
primitiveType : PrimitiveType.TRIANGLES
})
});
GeometryPipeline.splitLongitude(instance);
expect(instance.geometry).not.toBeDefined();
expect(instance.westHemisphereGeometry).toBeDefined();
expect(instance.westHemisphereGeometry.indices).toBeDefined();
expect(instance.westHemisphereGeometry.indices.length).toEqual(3);
expect(instance.westHemisphereGeometry.attributes.position).toBeDefined();
expect(instance.westHemisphereGeometry.attributes.position.values.length).toEqual(3 * 3);
expect(instance.eastHemisphereGeometry).toBeDefined();
expect(instance.eastHemisphereGeometry.indices).toBeDefined();
expect(instance.eastHemisphereGeometry.indices.length).toEqual(6);
expect(instance.eastHemisphereGeometry.attributes.position).toBeDefined();
expect(instance.eastHemisphereGeometry.attributes.position.values.length).toEqual(5 * 3);
});
it('splitLongitude subdivides triangle crossing the international date line, p0 ahead', function() {
var instance = new GeometryInstance({
geometry : new Geometry({
attributes : {
position : new GeometryAttribute({
componentDatatype : ComponentDatatype.DOUBLE,
componentsPerAttribute : 3,
values : new Float64Array([-1.0, 1.0, 0.0, -1.0, -1.0, 0.0, -2.0, -1.0, 0.0])
})
},
indices : new Uint16Array([0, 1, 2]),
primitiveType : PrimitiveType.TRIANGLES
})
});
GeometryPipeline.splitLongitude(instance);
expect(instance.geometry).not.toBeDefined();
expect(instance.westHemisphereGeometry).toBeDefined();
expect(instance.westHemisphereGeometry.indices).toBeDefined();
expect(instance.westHemisphereGeometry.indices.length).toEqual(6);
expect(instance.westHemisphereGeometry.attributes.position).toBeDefined();
expect(instance.westHemisphereGeometry.attributes.position.values.length).toEqual(5 * 3);
expect(instance.eastHemisphereGeometry).toBeDefined();
expect(instance.eastHemisphereGeometry.indices).toBeDefined();
expect(instance.eastHemisphereGeometry.indices.length).toEqual(3);
expect(instance.eastHemisphereGeometry.attributes.position).toBeDefined();
expect(instance.eastHemisphereGeometry.attributes.position.values.length).toEqual(3 * 3);
});
it('splitLongitude subdivides triangle crossing the international date line, p1 ahead', function() {
var instance = new GeometryInstance({
geometry : new Geometry({
attributes : {
position : new GeometryAttribute({
componentDatatype : ComponentDatatype.DOUBLE,
componentsPerAttribute : 3,
values : new Float64Array([-2.0, -1.0, 0.0, -1.0, 1.0, 0.0, -1.0, -1.0, 0.0])
})
},
indices : new Uint16Array([0, 1, 2]),
primitiveType : PrimitiveType.TRIANGLES
})
});
GeometryPipeline.splitLongitude(instance);
expect(instance.geometry).not.toBeDefined();
expect(instance.westHemisphereGeometry).toBeDefined();
expect(instance.westHemisphereGeometry.indices).toBeDefined();
expect(instance.westHemisphereGeometry.indices.length).toEqual(6);
expect(instance.westHemisphereGeometry.attributes.position).toBeDefined();
expect(instance.westHemisphereGeometry.attributes.position.values.length).toEqual(5 * 3);
expect(instance.eastHemisphereGeometry).toBeDefined();
expect(instance.eastHemisphereGeometry.indices).toBeDefined();
expect(instance.eastHemisphereGeometry.indices.length).toEqual(3);
expect(instance.eastHemisphereGeometry.attributes.position).toBeDefined();
expect(instance.eastHemisphereGeometry.attributes.position.values.length).toEqual(3 * 3);
});
it('splitLongitude subdivides triangle crossing the international date line, p2 ahead', function() {
var instance = new GeometryInstance({
geometry : new Geometry({
attributes : {
position : new GeometryAttribute({
componentDatatype : ComponentDatatype.DOUBLE,
componentsPerAttribute : 3,
values : new Float64Array([-1.0, -1.0, 0.0, -2.0, -1.0, 0.0, -1.0, 1.0, 0.0])
})
},
indices : new Uint16Array([0, 1, 2]),
primitiveType : PrimitiveType.TRIANGLES
})
});
GeometryPipeline.splitLongitude(instance);
expect(instance.geometry).not.toBeDefined();
expect(instance.westHemisphereGeometry).toBeDefined();
expect(instance.westHemisphereGeometry.indices).toBeDefined();
expect(instance.westHemisphereGeometry.indices.length).toEqual(6);
expect(instance.westHemisphereGeometry.attributes.position).toBeDefined();
expect(instance.westHemisphereGeometry.attributes.position.values.length).toEqual(5 * 3);
expect(instance.eastHemisphereGeometry).toBeDefined();
expect(instance.eastHemisphereGeometry.indices).toBeDefined();
expect(instance.eastHemisphereGeometry.indices.length).toEqual(3);
expect(instance.eastHemisphereGeometry.attributes.position).toBeDefined();
expect(instance.eastHemisphereGeometry.attributes.position.values.length).toEqual(3 * 3);
});
it('splitLongitude returns offset triangle that touches the international date line', function() {
var instance = new GeometryInstance({
geometry : new Geometry({
attributes : {
position : new GeometryAttribute({
componentDatatype : ComponentDatatype.DOUBLE,
componentsPerAttribute : 3,
values : new Float64Array([-1.0, 0.0, 1.0, -1.0, CesiumMath.EPSILON14, 2.0, -2.0, 2.0, 2.0])
})
},
indices : new Uint16Array([0, 1, 2]),
primitiveType : PrimitiveType.TRIANGLES
})
});
GeometryPipeline.splitLongitude(instance);
var geometry = instance.geometry;
expect(geometry.indices).toEqual([0, 1, 2]);
var positions = geometry.attributes.position.values;
expect(positions).toEqual([-1.0, CesiumMath.EPSILON6, 1.0, -1.0, CesiumMath.EPSILON6, 2.0, -2.0, 2.0, 2.0]);
expect(positions.length).toEqual(3 * 3);
});
it('splitLongitude returns the same points if the triangle doesn\'t cross the international date line, behind', function() {
var instance = new GeometryInstance({
geometry : new Geometry({
attributes : {
position : new GeometryAttribute({
componentDatatype : ComponentDatatype.DOUBLE,
componentsPerAttribute : 3,
values : new Float64Array([-1.0, -1.0, 1.0, -1.0, -2.0, 1.0, -1.0, -2.0, 2.0])
})
},
indices : new Uint16Array([0, 1, 2]),
primitiveType : PrimitiveType.TRIANGLES
})
});
GeometryPipeline.splitLongitude(instance);
var geometry = instance.geometry;
expect(geometry.indices).toEqual([0, 1, 2]);
var positions = geometry.attributes.position.values;
expect(positions).toEqual([-1.0, -1.0, 1.0, -1.0, -2.0, 1.0, -1.0, -2.0, 2.0]);
expect(positions.length).toEqual(3 * 3);
});
it('splitLongitude returns the same points if the triangle doesn\'t cross the international date line, ahead', function() {
var instance = new GeometryInstance({
geometry : new Geometry({
attributes : {
position : new GeometryAttribute({
componentDatatype : ComponentDatatype.DOUBLE,
componentsPerAttribute : 3,
values : new Float64Array([-1.0, 1.0, 1.0, -1.0, 2.0, 1.0, -1.0, 2.0, 2.0])
})
},
indices : new Uint16Array([0, 1, 2]),
primitiveType : PrimitiveType.TRIANGLES
})
});
GeometryPipeline.splitLongitude(instance);
var geometry = instance.geometry;
expect(geometry.indices).toEqual([0, 1, 2]);
var positions = geometry.attributes.position.values;
expect(positions).toEqual([-1.0, 1.0, 1.0, -1.0, 2.0, 1.0, -1.0, 2.0, 2.0]);
expect(positions.length).toEqual(3 * 3);
});
it('splitLongitude returns the same points if the triangle doesn\'t cross the international date line, positive x', function() {
var instance = new GeometryInstance({
geometry : new Geometry({
attributes : {
position : new GeometryAttribute({
componentDatatype : ComponentDatatype.DOUBLE,
componentsPerAttribute : 3,
values : new Float64Array([1.0, 1.0, 1.0, 1.0, 2.0, 1.0, 1.0, 2.0, 2.0])
})
},
indices : new Uint16Array([0, 1, 2]),
primitiveType : PrimitiveType.TRIANGLES
})
});
GeometryPipeline.splitLongitude(instance);
var geometry = instance.geometry;
expect(geometry.indices).toEqual([0, 1, 2]);
var positions = geometry.attributes.position.values;
expect(positions).toEqual([1.0, 1.0, 1.0, 1.0, 2.0, 1.0, 1.0, 2.0, 2.0]);
expect(positions.length).toEqual(3 * 3);
});
it('splitLongitude computes all attributes for a triangle crossing the international date line', function() {
var instance = new GeometryInstance({
geometry : new Geometry({
attributes : {
position : new GeometryAttribute({
componentDatatype : ComponentDatatype.DOUBLE,
componentsPerAttribute : 3,
values : new Float64Array([-2.0, -1.0, 0.0, -3.0, 1.0, 0.0, -1.0, 1.0, 0.0])
}),
normal : new GeometryAttribute({
componentDatatype : ComponentDatatype.FLOAT,
componentsPerAttribute : 3,
values : new Float32Array([0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0])
}),
tangent : new GeometryAttribute({
componentDatatype : ComponentDatatype.FLOAT,
componentsPerAttribute : 3,
values : new Float32Array([-1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0])
}),
bitangent : new GeometryAttribute({
componentDatatype : ComponentDatatype.FLOAT,
componentsPerAttribute : 3,
values : new Float32Array([0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0])
}),
st : new GeometryAttribute({
componentDatatype : ComponentDatatype.FLOAT,
componentsPerAttribute : 2,
values : new Float32Array([0.0, 0.0, 1.0, 0.0, 0.5, 0.5])
})
},
indices : new Uint16Array([1, 2, 0]),
primitiveType : PrimitiveType.TRIANGLES
})
});
GeometryPipeline.splitLongitude(instance);
expect(instance.geometry).not.toBeDefined();
expect(instance.westHemisphereGeometry).toBeDefined();
expect(instance.westHemisphereGeometry.indices).toBeDefined();
expect(instance.westHemisphereGeometry.indices.length).toEqual(3);
expect(instance.westHemisphereGeometry.attributes.position).toBeDefined();
expect(instance.westHemisphereGeometry.attributes.position.values.length).toEqual(3 * 3);
expect(instance.westHemisphereGeometry.attributes.normal).toBeDefined();
expect(instance.westHemisphereGeometry.attributes.normal.values.length).toEqual(3 * 3);
expect(instance.westHemisphereGeometry.attributes.bitangent).toBeDefined();
expect(instance.westHemisphereGeometry.attributes.bitangent.values.length).toEqual(3 * 3);
expect(instance.westHemisphereGeometry.attributes.tangent).toBeDefined();
expect(instance.westHemisphereGeometry.attributes.tangent.values.length).toEqual(3 * 3);
expect(instance.westHemisphereGeometry.attributes.st).toBeDefined();
expect(instance.westHemisphereGeometry.attributes.st.values.length).toEqual(3 * 2);
expect(instance.eastHemisphereGeometry).toBeDefined();
expect(instance.eastHemisphereGeometry.indices).toBeDefined();
expect(instance.eastHemisphereGeometry.indices.length).toEqual(6);
expect(instance.eastHemisphereGeometry.attributes.position).toBeDefined();
expect(instance.eastHemisphereGeometry.attributes.position.values.length).toEqual(5 * 3);
expect(instance.eastHemisphereGeometry.attributes.normal).toBeDefined();
expect(instance.eastHemisphereGeometry.attributes.normal.values.length).toEqual(5 * 3);
expect(instance.eastHemisphereGeometry.attributes.bitangent).toBeDefined();
expect(instance.eastHemisphereGeometry.attributes.bitangent.values.length).toEqual(5 * 3);
expect(instance.eastHemisphereGeometry.attributes.tangent).toBeDefined();
expect(instance.eastHemisphereGeometry.attributes.tangent.values.length).toEqual(5 * 3);
expect(instance.eastHemisphereGeometry.attributes.st).toBeDefined();
expect(instance.eastHemisphereGeometry.attributes.st.values.length).toEqual(5 * 2);
});
it('splitLongitude subdivides line crossing the international date line', function() {
var instance = new GeometryInstance({
geometry : new Geometry({
attributes : {
position : new GeometryAttribute({
componentDatatype : ComponentDatatype.DOUBLE,
componentsPerAttribute : 3,
values : new Float64Array([-1.0, -1.0, 0.0, -1.0, 1.0, 2.0])
})
},
indices : new Uint16Array([0, 1]),
primitiveType : PrimitiveType.LINES
})
});
GeometryPipeline.splitLongitude(instance);
expect(instance.geometry).not.toBeDefined();
expect(instance.westHemisphereGeometry).toBeDefined();
expect(instance.westHemisphereGeometry.indices).toBeDefined();
expect(instance.westHemisphereGeometry.indices.length).toEqual(2);
expect(instance.westHemisphereGeometry.attributes.position).toBeDefined();
expect(instance.westHemisphereGeometry.attributes.position.values.length).toEqual(2 * 3);
expect(instance.eastHemisphereGeometry).toBeDefined();
expect(instance.eastHemisphereGeometry.indices).toBeDefined();
expect(instance.eastHemisphereGeometry.indices.length).toEqual(2);
expect(instance.eastHemisphereGeometry.attributes.position).toBeDefined();
expect(instance.eastHemisphereGeometry.attributes.position.values.length).toEqual(2 * 3);
});
it('splitLongitude returns offset line that touches the international date line', function() {
var instance = new GeometryInstance({
geometry : new Geometry({
attributes : {
position : new GeometryAttribute({
componentDatatype : ComponentDatatype.DOUBLE,
componentsPerAttribute : 3,
values : new Float64Array([-1.0, 0.0, 0.0, -1.0, 1.0, 2.0])
})
},
indices : new Uint16Array([0, 1]),
primitiveType : PrimitiveType.LINES
})
});
GeometryPipeline.splitLongitude(instance);
var geometry = instance.geometry;
expect(geometry.indices).toEqual([0, 1]);
var positions = geometry.attributes.position.values;
expect(positions).toEqual([-1.0, CesiumMath.EPSILON6, 0.0, -1.0, 1.0, 2.0]);
});
it('splitLongitude returns the same points if the line doesn\'t cross the international date line', function() {
var instance = new GeometryInstance({
geometry : new Geometry({
attributes : {
position : new GeometryAttribute({
componentDatatype : ComponentDatatype.DOUBLE,
componentsPerAttribute : 3,
values : new Float64Array([1.0, 1.0, 0.0, 1.0, 1.0, 2.0])
})
},
indices : new Uint16Array([0, 1]),
primitiveType : PrimitiveType.LINES
})
});
GeometryPipeline.splitLongitude(instance);
var geometry = instance.geometry;
expect(geometry.indices).toEqual([0, 1]);
var positions = geometry.attributes.position.values;
expect(positions).toEqual([1.0, 1.0, 0.0, 1.0, 1.0, 2.0]);
});
it('splitLongitude does nothing for points', function() {
var instance = new GeometryInstance({
geometry : new Geometry({
attributes : {
position : new GeometryAttribute({
componentDatatype : ComponentDatatype.DOUBLE,
componentsPerAttribute : 3,
values : new Float64Array([1.0, 1.0, 0.0, 1.0, 1.0, 2.0])
})
},
primitiveType : PrimitiveType.POINTS
})
});
GeometryPipeline.splitLongitude(instance);
var geometry = instance.geometry;
expect(geometry.indices).not.toBeDefined();
var positions = geometry.attributes.position.values;
expect(positions).toEqual([1.0, 1.0, 0.0, 1.0, 1.0, 2.0]);
});
describe('splitLongitude polylines', function() {
it('subdivides wide line crossing the international date line', function() {
var instance = new GeometryInstance({
geometry : new Geometry({
attributes : {
position : new GeometryAttribute({
componentDatatype : ComponentDatatype.DOUBLE,
componentsPerAttribute : 3,
values : new Float64Array([-1.0, -1.0, 0.0, -1.0, -1.0, 0.0, -1.0, 1.0, 2.0, -1.0, 1.0, 2.0])
}),
nextPosition : new GeometryAttribute({
componentDatatype : ComponentDatatype.DOUBLE,
componentsPerAttribute : 3,
values : new Float64Array([-1.0, 1.0, 2.0, -1.0, 1.0, 2.0, -1.0, 2.0, 3.0, -1.0, 2.0, 3.0])
}),
prevPosition : new GeometryAttribute({
componentDatatype : ComponentDatatype.DOUBLE,
componentsPerAttribute : 3,
values : new Float64Array([-1.0, -2.0, -1.0, -1.0, -2.0, -1.0, -1.0, -1.0, 0.0, -1.0, -1.0, 0.0])
}),
expandAndWidth : new GeometryAttribute({
componentDatatype : ComponentDatatype.FLOAT,
componentsPerAttribute : 2,
values : new Float32Array([-1.0, 5.0, 1.0, 5.0, -1.0, -5.0, 1.0, -5.0])
})
},
indices : new Uint16Array([0, 2, 1, 1, 2, 3]),
primitiveType : PrimitiveType.TRIANGLES,
geometryType : GeometryType.POLYLINES
})
});
GeometryPipeline.splitLongitude(instance);
expect(instance.geometry).not.toBeDefined();
expect(instance.westHemisphereGeometry).toBeDefined();
expect(instance.westHemisphereGeometry.indices).toBeDefined();
expect(instance.westHemisphereGeometry.indices.length).toEqual(6);
expect(instance.westHemisphereGeometry.attributes.position).toBeDefined();
expect(instance.westHemisphereGeometry.attributes.position.values.length).toEqual(4 * 3);
expect(instance.westHemisphereGeometry.attributes.nextPosition).toBeDefined();
expect(instance.westHemisphereGeometry.attributes.nextPosition.values.length).toEqual(4 * 3);
expect(instance.westHemisphereGeometry.attributes.prevPosition).toBeDefined();
expect(instance.westHemisphereGeometry.attributes.prevPosition.values.length).toEqual(4 * 3);
expect(instance.westHemisphereGeometry.attributes.expandAndWidth).toBeDefined();
expect(instance.westHemisphereGeometry.attributes.expandAndWidth.values.length).toEqual(4 * 2);
expect(instance.eastHemisphereGeometry).toBeDefined();
expect(instance.eastHemisphereGeometry.indices).toBeDefined();
expect(instance.eastHemisphereGeometry.indices.length).toEqual(6);
expect(instance.eastHemisphereGeometry.attributes.position).toBeDefined();
expect(instance.eastHemisphereGeometry.attributes.position.values.length).toEqual(4 * 3);
expect(instance.eastHemisphereGeometry.attributes.nextPosition).toBeDefined();
expect(instance.eastHemisphereGeometry.attributes.nextPosition.values.length).toEqual(4 * 3);
expect(instance.eastHemisphereGeometry.attributes.prevPosition).toBeDefined();
expect(instance.eastHemisphereGeometry.attributes.prevPosition.values.length).toEqual(4 * 3);
expect(instance.eastHemisphereGeometry.attributes.expandAndWidth).toBeDefined();
expect(instance.eastHemisphereGeometry.attributes.expandAndWidth.values.length).toEqual(4 * 2);
});
it('returns offset wide line with first point on the IDL and the second is east', function() {
var instance = new GeometryInstance({
geometry : new Geometry({
attributes : {
position : new GeometryAttribute({
componentDatatype : ComponentDatatype.DOUBLE,
componentsPerAttribute : 3,
values : new Float64Array([-1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 1.0, 2.0, -1.0, 1.0, 2.0])
}),
nextPosition : new GeometryAttribute({
componentDatatype : ComponentDatatype.DOUBLE,
componentsPerAttribute : 3,
values : new Float64Array([-1.0, 1.0, 2.0, -1.0, 1.0, 2.0, -1.0, 2.0, 3.0, -1.0, 2.0, 3.0])
}),
prevPosition : new GeometryAttribute({
componentDatatype : ComponentDatatype.DOUBLE,
componentsPerAttribute : 3,
values : new Float64Array([-1.0, -2.0, -1.0, -1.0, -2.0, -1.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0])
}),
expandAndWidth : new GeometryAttribute({
componentDatatype : ComponentDatatype.FLOAT,
componentsPerAttribute : 2,
values : new Float32Array([-1.0, 5.0, 1.0, 5.0, -1.0, -5.0, 1.0, -5.0])
})
},
indices : new Uint16Array([0, 2, 1, 1, 2, 3]),
primitiveType : PrimitiveType.TRIANGLES,
geometryType : GeometryType.POLYLINES
})
});
GeometryPipeline.splitLongitude(instance);
var geometry = instance.geometry;
expect(geometry.indices).toEqual([0, 2, 1, 1, 2, 3]);
var positions = geometry.attributes.position.values;
var nextPositions = geometry.attributes.nextPosition.values;
var prevPositions = geometry.attributes.prevPosition.values;
expect(positions).toEqual([-1.0, CesiumMath.EPSILON6, 0.0, -1.0, CesiumMath.EPSILON6, 0.0, -1.0, 1.0, 2.0, -1.0, 1.0, 2.0]);
expect(prevPositions).toEqual([-1.0, CesiumMath.EPSILON6, 0.0, -1.0, CesiumMath.EPSILON6, 0.0, -1.0, CesiumMath.EPSILON6, 0.0, -1.0, CesiumMath.EPSILON6, 0.0]);
expect(nextPositions).toEqual([-1.0, 1.0, 2.0, -1.0, 1.0, 2.0, -1.0, 2.0, 3.0, -1.0, 2.0, 3.0]);
});
it('returns offset wide line with first point on the IDL and the second is west', function() {
var instance = new GeometryInstance({
geometry : new Geometry({
attributes : {
position : new GeometryAttribute({
componentDatatype : ComponentDatatype.DOUBLE,
componentsPerAttribute : 3,
values : new Float64Array([-1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, -1.0, 2.0, -1.0, -1.0, 2.0])
}),
nextPosition : new GeometryAttribute({
componentDatatype : ComponentDatatype.DOUBLE,
componentsPerAttribute : 3,
values : new Float64Array([-1.0, -1.0, 2.0, -1.0, -1.0, 2.0, -1.0, -2.0, 0.0, -1.0, -2.0, 0.0])
}),
prevPosition : new GeometryAttribute({
componentDatatype : ComponentDatatype.DOUBLE,
componentsPerAttribute : 3,
values : new Float64Array([-1.0, 1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0])
}),
expandAndWidth : new GeometryAttribute({
componentDatatype : ComponentDatatype.FLOAT,
componentsPerAttribute : 2,
values : new Float32Array([-1.0, 5.0, 1.0, 5.0, -1.0, -5.0, 1.0, -5.0])
})
},
indices : new Uint16Array([0, 2, 1, 1, 2, 3]),
primitiveType : PrimitiveType.TRIANGLES,
geometryType : GeometryType.POLYLINES
})
});
GeometryPipeline.splitLongitude(instance);
var geometry = instance.geometry;
expect(geometry.indices).toEqual([0, 2, 1, 1, 2, 3]);
var positions = geometry.attributes.position.values;
var nextPositions = geometry.attributes.nextPosition.values;
var prevPositions = geometry.attributes.prevPosition.values;
expect(positions).toEqual([-1.0, -CesiumMath.EPSILON6, 0.0, -1.0, -CesiumMath.EPSILON6, 0.0, -1.0, -1.0, 2.0, -1.0, -1.0, 2.0]);
expect(prevPositions).toEqual([-1.0, -CesiumMath.EPSILON6, 0.0, -1.0, -CesiumMath.EPSILON6, 0.0, -1.0, -CesiumMath.EPSILON6, 0.0, -1.0, -CesiumMath.EPSILON6, 0.0]);
expect(nextPositions).toEqual([-1.0, -1.0, 2.0, -1.0, -1.0, 2.0, -1.0, -2.0, 0.0, -1.0, -2.0, 0.0]);
});
it('returns offset wide line with first point is east and the second is on the IDL', function() {
var instance = new GeometryInstance({
geometry : new Geometry({
attributes : {
position : new GeometryAttribute({
componentDatatype : ComponentDatatype.DOUBLE,
componentsPerAttribute : 3,
values : new Float64Array([-1.0, 1.0, 2.0, -1.0, 1.0, 2.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0])
}),
nextPosition : new GeometryAttribute({
componentDatatype : ComponentDatatype.DOUBLE,
componentsPerAttribute : 3,
values : new Float64Array([-1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, -1.0, 2.0, -1.0, -1.0, 2.0])
}),
prevPosition : new GeometryAttribute({
componentDatatype : ComponentDatatype.DOUBLE,
componentsPerAttribute : 3,
values : new Float64Array([-2.0, 2.0, 2.0, -1.0, 2.0, 2.0, -1.0, 1.0, 2.0, -1.0, 1.0, 2.0])
}),
expandAndWidth : new GeometryAttribute({
componentDatatype : ComponentDatatype.FLOAT,
componentsPerAttribute : 2,
values : new Float32Array([-1.0, 5.0, 1.0, 5.0, -1.0, -5.0, 1.0, -5.0])
})
},
indices : new Uint16Array([0, 2, 1, 1, 2, 3]),
primitiveType : PrimitiveType.TRIANGLES,
geometryType : GeometryType.POLYLINES
})
});
GeometryPipeline.splitLongitude(instance);
var geometry = instance.geometry;
expect(geometry.indices).toEqual([0, 2, 1, 1, 2, 3]);
var positions = geometry.attributes.position.values;
var nextPositions = geometry.attributes.nextPosition.values;
var prevPositions = geometry.attributes.prevPosition.values;
expect(positions).toEqual([-1.0, 1.0, 2.0, -1.0, 1.0, 2.0, -1.0, CesiumMath.EPSILON6, 0.0, -1.0, CesiumMath.EPSILON6, 0.0]);
expect(nextPositions).toEqual([-1.0, CesiumMath.EPSILON6, 0.0, -1.0, CesiumMath.EPSILON6, 0.0, -1.0, CesiumMath.EPSILON6, 0.0, -1.0, CesiumMath.EPSILON6, 0.0]);
expect(prevPositions).toEqual([-2.0, 2.0, 2.0, -1.0, 2.0, 2.0, -1.0, 1.0, 2.0, -1.0, 1.0, 2.0]);
});
it('returns offset wide line with first point is west and the second is on the IDL', function() {
var instance = new GeometryInstance({
geometry : new Geometry({
attributes : {
position : new GeometryAttribute({
componentDatatype : ComponentDatatype.DOUBLE,
componentsPerAttribute : 3,
values : new Float64Array([-1.0, -1.0, 2.0, -1.0, -1.0, 2.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0])
}),
nextPosition : new GeometryAttribute({
componentDatatype : ComponentDatatype.DOUBLE,
componentsPerAttribute : 3,
values : new Float64Array([-1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 1.0, 2.0, -1.0, 1.0, 2.0])
}),
prevPosition : new GeometryAttribute({
componentDatatype : ComponentDatatype.DOUBLE,
componentsPerAttribute : 3,
values : new Float64Array([-2.0, -2.0, 2.0, -1.0, -2.0, 2.0, -1.0, -1.0, 2.0, -1.0, -1.0, 2.0])
}),
expandAndWidth : new GeometryAttribute({
componentDatatype : ComponentDatatype.FLOAT,
componentsPerAttribute : 2,
values : new Float32Array([-1.0, 5.0, 1.0, 5.0, -1.0, -5.0, 1.0, -5.0])
})
},
indices : new Uint16Array([0, 2, 1, 1, 2, 3]),
primitiveType : PrimitiveType.TRIANGLES,
geometryType : GeometryType.POLYLINES
})
});
GeometryPipeline.splitLongitude(instance);
var geometry = instance.geometry;
expect(geometry.indices).toEqual([0, 2, 1, 1, 2, 3]);
var positions = geometry.attributes.position.values;
var nextPositions = geometry.attributes.nextPosition.values;
var prevPositions = geometry.attributes.prevPosition.values;
expect(positions).toEqual([-1.0, -1.0, 2.0, -1.0, -1.0, 2.0, -1.0, -CesiumMath.EPSILON6, 0.0, -1.0, -CesiumMath.EPSILON6, 0.0]);
expect(nextPositions).toEqual([-1.0, -CesiumMath.EPSILON6, 0.0, -1.0, -CesiumMath.EPSILON6, 0.0, -1.0, -CesiumMath.EPSILON6, 0.0, -1.0, -CesiumMath.EPSILON6, 0.0]);
expect(prevPositions).toEqual([-2.0, -2.0, 2.0, -1.0, -2.0, 2.0, -1.0, -1.0, 2.0, -1.0, -1.0, 2.0]);
});
it('returns the same points if the wide line doesn\'t cross the international date line', function() {
var instance = new GeometryInstance({
geometry : new Geometry({
attributes : {
position : new GeometryAttribute({
componentDatatype : ComponentDatatype.DOUBLE,
componentsPerAttribute : 3,
values : new Float64Array([-1.0, 1.0, 0.0, -1.0, 1.0, 0.0, -1.0, 1.0, 2.0, -1.0, 1.0, 2.0])
}),
nextPosition : new GeometryAttribute({
componentDatatype : ComponentDatatype.DOUBLE,
componentsPerAttribute : 3,
values : new Float64Array([-1.0, 1.0, 2.0, -1.0, 1.0, 2.0, -1.0, 2.0, 3.0, -1.0, 2.0, 3.0])
}),
prevPosition : new GeometryAttribute({
componentDatatype : ComponentDatatype.DOUBLE,
componentsPerAttribute : 3,
values : new Float64Array([-1.0, -2.0, -1.0, -1.0, -2.0, -1.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0])
}),
expandAndWidth : new GeometryAttribute({
componentDatatype : ComponentDatatype.FLOAT,
componentsPerAttribute : 2,
values : new Float32Array([-1.0, 5.0, 1.0, 5.0, -1.0, -5.0, 1.0, -5.0])
})
},
indices : new Uint16Array([0, 2, 1, 1, 2, 3]),
primitiveType : PrimitiveType.TRIANGLES,
geometryType : GeometryType.POLYLINES
})
});
GeometryPipeline.splitLongitude(instance);
var geometry = instance.geometry;
expect(geometry.indices).toEqual([0, 2, 1, 1, 2, 3]);
var positions = geometry.attributes.position.values;
expect(positions).toEqual([-1.0, 1.0, 0.0, -1.0, 1.0, 0.0, -1.0, 1.0, 2.0, -1.0, 1.0, 2.0]);
});
});
it('splitLongitude throws when geometry is undefined', function() {
expect(function() {
return GeometryPipeline.splitLongitude();
}).toThrowDeveloperError();
});
});