You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
505 lines
18 KiB
JavaScript
505 lines
18 KiB
JavaScript
import { BoundingSphere } from "../../Source/Cesium.js";
|
|
import { Cartesian3 } from "../../Source/Cesium.js";
|
|
import { Ellipsoid } from "../../Source/Cesium.js";
|
|
import { EllipsoidalOccluder } from "../../Source/Cesium.js";
|
|
import { IntersectionTests } from "../../Source/Cesium.js";
|
|
import { Math as CesiumMath } from "../../Source/Cesium.js";
|
|
import { Ray } from "../../Source/Cesium.js";
|
|
import { Rectangle } from "../../Source/Cesium.js";
|
|
|
|
describe("Core/EllipsoidalOccluder", function () {
|
|
it("uses ellipsoid", function () {
|
|
var ellipsoid = new Ellipsoid(2.0, 3.0, 4.0);
|
|
var occluder = new EllipsoidalOccluder(ellipsoid);
|
|
expect(occluder.ellipsoid).toEqual(ellipsoid);
|
|
});
|
|
|
|
it("throws if ellipsoid is not provided to constructor", function () {
|
|
function createOccluderWithoutEllipsoid() {
|
|
return new EllipsoidalOccluder(undefined, new Cartesian3(1.0, 2.0, 3.0));
|
|
}
|
|
expect(createOccluderWithoutEllipsoid).toThrowDeveloperError();
|
|
});
|
|
|
|
it("isPointVisible example works as claimed", function () {
|
|
var cameraPosition = new Cartesian3(0, 0, 2.5);
|
|
var ellipsoid = new Ellipsoid(1.0, 1.1, 0.9);
|
|
var occluder = new EllipsoidalOccluder(ellipsoid, cameraPosition);
|
|
var point = new Cartesian3(0, -3, -3);
|
|
expect(occluder.isPointVisible(point)).toEqual(true);
|
|
});
|
|
|
|
it("isScaledSpacePointVisible example works as claimed", function () {
|
|
var cameraPosition = new Cartesian3(0, 0, 2.5);
|
|
var ellipsoid = new Ellipsoid(1.0, 1.1, 0.9);
|
|
var occluder = new EllipsoidalOccluder(ellipsoid, cameraPosition);
|
|
var point = new Cartesian3(0, -3, -3);
|
|
var scaledSpacePoint = ellipsoid.transformPositionToScaledSpace(point);
|
|
expect(occluder.isScaledSpacePointVisible(scaledSpacePoint)).toEqual(true);
|
|
});
|
|
|
|
it("isScaledSpacePointVisiblePossiblyUnderEllipsoid example works as claimed", function () {
|
|
// Tests points that are halfway inside a unit sphere:
|
|
// 1) on the diagonal
|
|
// 2) on the +y-axis
|
|
// The camera is on the +z-axis so it will be able to see the diagonal point but not the +y-axis point.
|
|
|
|
var cameraPosition = new Cartesian3(0, 0, 1.0);
|
|
var ellipsoid = new Ellipsoid(1.0, 1.0, 1.0);
|
|
var occluder = new EllipsoidalOccluder(ellipsoid, cameraPosition);
|
|
var height = -0.5;
|
|
|
|
var direction = Cartesian3.normalize(
|
|
new Cartesian3(1.0, 1.0, 1.0),
|
|
new Cartesian3()
|
|
);
|
|
var point = Cartesian3.multiplyByScalar(direction, 0.5, new Cartesian3());
|
|
var scaledSpacePoint = occluder.computeHorizonCullingPoint(point, [point]);
|
|
var scaledSpacePointShrunk = occluder.computeHorizonCullingPointPossiblyUnderEllipsoid(
|
|
point,
|
|
[point],
|
|
height
|
|
);
|
|
|
|
expect(occluder.isScaledSpacePointVisible(scaledSpacePoint)).toEqual(false);
|
|
expect(
|
|
occluder.isScaledSpacePointVisiblePossiblyUnderEllipsoid(
|
|
scaledSpacePointShrunk,
|
|
height
|
|
)
|
|
).toEqual(true);
|
|
|
|
direction = new Cartesian3(0.0, 1.0, 0.0);
|
|
point = Cartesian3.multiplyByScalar(direction, 0.5, new Cartesian3());
|
|
scaledSpacePoint = occluder.computeHorizonCullingPoint(point, [point]);
|
|
scaledSpacePointShrunk = occluder.computeHorizonCullingPointPossiblyUnderEllipsoid(
|
|
point,
|
|
[point],
|
|
height
|
|
);
|
|
|
|
expect(occluder.isScaledSpacePointVisible(scaledSpacePoint)).toEqual(false);
|
|
expect(
|
|
occluder.isScaledSpacePointVisiblePossiblyUnderEllipsoid(
|
|
scaledSpacePointShrunk,
|
|
height
|
|
)
|
|
).toEqual(false);
|
|
});
|
|
|
|
it("reports not visible when point is directly behind ellipsoid", function () {
|
|
var ellipsoid = Ellipsoid.WGS84;
|
|
var occluder = new EllipsoidalOccluder(ellipsoid);
|
|
occluder.cameraPosition = new Cartesian3(7000000.0, 0.0, 0.0);
|
|
|
|
var point = new Cartesian3(-7000000, 0.0, 0.0);
|
|
expect(occluder.isPointVisible(point)).toEqual(false);
|
|
});
|
|
|
|
it("reports not visible when point is directly behind ellipsoid and camera is inside the ellispoid", function () {
|
|
var ellipsoid = Ellipsoid.WGS84;
|
|
var occluder = new EllipsoidalOccluder(ellipsoid);
|
|
occluder.cameraPosition = new Cartesian3(
|
|
ellipsoid.minimumRadius - 100,
|
|
0.0,
|
|
0.0
|
|
);
|
|
|
|
var point = new Cartesian3(-7000000, 0.0, 0.0);
|
|
expect(occluder.isPointVisible(point)).toEqual(false);
|
|
});
|
|
|
|
it("reports visible when point is in front of ellipsoid", function () {
|
|
var ellipsoid = Ellipsoid.WGS84;
|
|
var occluder = new EllipsoidalOccluder(ellipsoid);
|
|
occluder.cameraPosition = new Cartesian3(7000000.0, 0.0, 0.0);
|
|
|
|
var point = new Cartesian3(6900000.0, 0.0, 0.0);
|
|
expect(occluder.isPointVisible(point)).toEqual(true);
|
|
});
|
|
|
|
it("reports visible when point is in opposite direction from ellipsoid", function () {
|
|
var ellipsoid = Ellipsoid.WGS84;
|
|
var occluder = new EllipsoidalOccluder(ellipsoid);
|
|
occluder.cameraPosition = new Cartesian3(7000000.0, 0.0, 0.0);
|
|
|
|
var point = new Cartesian3(7100000.0, 0.0, 0.0);
|
|
expect(occluder.isPointVisible(point)).toEqual(true);
|
|
});
|
|
|
|
it("reports not visible when point is over horizon", function () {
|
|
var ellipsoid = Ellipsoid.WGS84;
|
|
var occluder = new EllipsoidalOccluder(ellipsoid);
|
|
occluder.cameraPosition = new Cartesian3(7000000.0, 0.0, 0.0);
|
|
|
|
var point = new Cartesian3(4510635.0, 4510635.0, 0.0);
|
|
expect(occluder.isPointVisible(point)).toEqual(false);
|
|
});
|
|
|
|
describe("computeHorizonCullingPoint", function () {
|
|
it("requires directionToPoint and positions", function () {
|
|
var ellipsoid = new Ellipsoid(12345.0, 12345.0, 12345.0);
|
|
var ellipsoidalOccluder = new EllipsoidalOccluder(ellipsoid);
|
|
var positions = [new Cartesian3(-12345.0, 12345.0, 12345.0)];
|
|
var directionToPoint = BoundingSphere.fromPoints(positions).center;
|
|
|
|
expect(function () {
|
|
ellipsoidalOccluder.computeHorizonCullingPoint(undefined, positions);
|
|
}).toThrowDeveloperError();
|
|
|
|
expect(function () {
|
|
ellipsoidalOccluder.computeHorizonCullingPoint(
|
|
directionToPoint,
|
|
undefined
|
|
);
|
|
}).toThrowDeveloperError();
|
|
});
|
|
|
|
it("returns point on ellipsoid when single position is on center line", function () {
|
|
var ellipsoid = new Ellipsoid(12345.0, 4567.0, 8910.0);
|
|
var ellipsoidalOccluder = new EllipsoidalOccluder(ellipsoid);
|
|
var positions = [new Cartesian3(12345.0, 0.0, 0.0)];
|
|
var directionToPoint = new Cartesian3(1.0, 0.0, 0.0);
|
|
|
|
var result = ellipsoidalOccluder.computeHorizonCullingPoint(
|
|
directionToPoint,
|
|
positions
|
|
);
|
|
|
|
expect(result.x).toEqualEpsilon(1.0, CesiumMath.EPSILON14);
|
|
expect(result.y).toEqualEpsilon(0.0, CesiumMath.EPSILON14);
|
|
expect(result.z).toEqualEpsilon(0.0, CesiumMath.EPSILON14);
|
|
});
|
|
|
|
it("returns undefined when horizon of single point is parallel to center line", function () {
|
|
var ellipsoid = new Ellipsoid(12345.0, 4567.0, 8910.0);
|
|
var ellipsoidalOccluder = new EllipsoidalOccluder(ellipsoid);
|
|
var positions = [new Cartesian3(0.0, 4567.0, 0.0)];
|
|
var directionToPoint = new Cartesian3(1.0, 0.0, 0.0);
|
|
|
|
var result = ellipsoidalOccluder.computeHorizonCullingPoint(
|
|
directionToPoint,
|
|
positions
|
|
);
|
|
expect(result).toBeUndefined();
|
|
});
|
|
|
|
it("returns undefined when single point is in the opposite direction of the center line", function () {
|
|
var ellipsoid = new Ellipsoid(12345.0, 4567.0, 8910.0);
|
|
var ellipsoidalOccluder = new EllipsoidalOccluder(ellipsoid);
|
|
var positions = [new Cartesian3(-14000.0, -1000.0, 0.0)];
|
|
var directionToPoint = new Cartesian3(1.0, 0.0, 0.0);
|
|
|
|
var result = ellipsoidalOccluder.computeHorizonCullingPoint(
|
|
directionToPoint,
|
|
positions
|
|
);
|
|
expect(result).toBeUndefined();
|
|
});
|
|
|
|
it("returns undefined when any point is in the opposite direction of the center line", function () {
|
|
var ellipsoid = new Ellipsoid(1.0, 1.0, 1.0);
|
|
var ellipsoidalOccluder = new EllipsoidalOccluder(ellipsoid);
|
|
var positions = [
|
|
new Cartesian3(2.0, 0.0, 0.0),
|
|
new Cartesian3(-1.0, 0.0, 0.0),
|
|
];
|
|
var directionToPoint = new Cartesian3(1.0, 0.0, 0.0);
|
|
|
|
var result = ellipsoidalOccluder.computeHorizonCullingPoint(
|
|
directionToPoint,
|
|
positions
|
|
);
|
|
expect(result).toBeUndefined();
|
|
});
|
|
|
|
it("returns undefined when the direction is zero", function () {
|
|
var ellipsoid = new Ellipsoid(1.0, 1.0, 1.0);
|
|
var ellipsoidalOccluder = new EllipsoidalOccluder(ellipsoid);
|
|
var positions = [new Cartesian3(1.0, 0.0, 0.0)];
|
|
var directionToPoint = new Cartesian3(0.0, 0.0, 0.0);
|
|
|
|
var result = ellipsoidalOccluder.computeHorizonCullingPoint(
|
|
directionToPoint,
|
|
positions
|
|
);
|
|
expect(result).toBeUndefined();
|
|
});
|
|
|
|
it("computes a point from a single position with a grazing altitude close to zero", function () {
|
|
var ellipsoid = new Ellipsoid(12345.0, 12345.0, 12345.0);
|
|
var ellipsoidalOccluder = new EllipsoidalOccluder(ellipsoid);
|
|
|
|
var positions = [
|
|
new Cartesian3(-12345.0, 12345.0, 12345.0),
|
|
new Cartesian3(-12346.0, 12345.0, 12345.0),
|
|
];
|
|
var boundingSphere = BoundingSphere.fromPoints(positions);
|
|
|
|
var firstPositionArray = [positions[0]];
|
|
var result = ellipsoidalOccluder.computeHorizonCullingPoint(
|
|
boundingSphere.center,
|
|
firstPositionArray
|
|
);
|
|
var unscaledResult = Cartesian3.multiplyComponents(
|
|
result,
|
|
ellipsoid.radii,
|
|
new Cartesian3()
|
|
);
|
|
|
|
// The grazing altitude of the ray from the horizon culling point to the
|
|
// position used to compute it should be very nearly zero.
|
|
var direction = Cartesian3.normalize(
|
|
Cartesian3.subtract(positions[0], unscaledResult, new Cartesian3()),
|
|
new Cartesian3()
|
|
);
|
|
var nearest = IntersectionTests.grazingAltitudeLocation(
|
|
new Ray(unscaledResult, direction),
|
|
ellipsoid
|
|
);
|
|
var nearestCartographic = ellipsoid.cartesianToCartographic(nearest);
|
|
expect(nearestCartographic.height).toEqualEpsilon(
|
|
0.0,
|
|
CesiumMath.EPSILON5
|
|
);
|
|
});
|
|
|
|
it("computes a point from multiple positions with a grazing altitude close to zero for one of the positions and less than zero for the others", function () {
|
|
var ellipsoid = new Ellipsoid(12345.0, 12345.0, 12345.0);
|
|
var ellipsoidalOccluder = new EllipsoidalOccluder(ellipsoid);
|
|
|
|
var positions = [
|
|
new Cartesian3(-12345.0, 12345.0, 12345.0),
|
|
new Cartesian3(-12346.0, 12345.0, 12345.0),
|
|
new Cartesian3(-12446.0, 12445.0, 12445.0),
|
|
];
|
|
var boundingSphere = BoundingSphere.fromPoints(positions);
|
|
|
|
var result = ellipsoidalOccluder.computeHorizonCullingPoint(
|
|
boundingSphere.center,
|
|
positions
|
|
);
|
|
var unscaledResult = Cartesian3.multiplyComponents(
|
|
result,
|
|
ellipsoid.radii,
|
|
new Cartesian3()
|
|
);
|
|
|
|
// The grazing altitude of the ray from the horizon culling point to the
|
|
// position used to compute it should be very nearly zero.
|
|
var foundOneNearZero = false;
|
|
for (var i = 0; i < positions.length; ++i) {
|
|
var direction = Cartesian3.normalize(
|
|
Cartesian3.subtract(positions[i], unscaledResult, new Cartesian3()),
|
|
new Cartesian3()
|
|
);
|
|
var nearest = IntersectionTests.grazingAltitudeLocation(
|
|
new Ray(unscaledResult, direction),
|
|
ellipsoid
|
|
);
|
|
var nearestCartographic = ellipsoid.cartesianToCartographic(nearest);
|
|
if (Math.abs(nearestCartographic.height) < CesiumMath.EPSILON5) {
|
|
foundOneNearZero = true;
|
|
} else {
|
|
expect(nearestCartographic.height).toBeLessThan(0.0);
|
|
}
|
|
}
|
|
|
|
expect(foundOneNearZero).toBe(true);
|
|
});
|
|
|
|
it("computes a point under the ellipsoid with computeHorizonCullingPointPossiblyUnderEllipsoid", function () {
|
|
var ellipsoid = new Ellipsoid(12345.0, 4567.0, 8910.0);
|
|
var ellipsoidalOccluder = new EllipsoidalOccluder(ellipsoid);
|
|
var positions = [new Cartesian3(12344.0, 0.0, 0.0)];
|
|
var directionToPoint = new Cartesian3(1.0, 0.0, 0.0);
|
|
|
|
var result = ellipsoidalOccluder.computeHorizonCullingPointPossiblyUnderEllipsoid(
|
|
directionToPoint,
|
|
positions,
|
|
-1.0
|
|
);
|
|
|
|
expect(result.x).toEqualEpsilon(1.0, CesiumMath.EPSILON14);
|
|
expect(result.y).toEqualEpsilon(0.0, CesiumMath.EPSILON14);
|
|
expect(result.z).toEqualEpsilon(0.0, CesiumMath.EPSILON14);
|
|
});
|
|
});
|
|
|
|
describe("computeHorizonCullingPointFromVertices", function () {
|
|
it("requires directionToPoint, vertices, and stride", function () {
|
|
var ellipsoid = new Ellipsoid(12345.0, 12345.0, 12345.0);
|
|
var ellipsoidalOccluder = new EllipsoidalOccluder(ellipsoid);
|
|
|
|
var positions = [
|
|
new Cartesian3(-12345.0, 12345.0, 12345.0),
|
|
new Cartesian3(-12346.0, 12345.0, 12345.0),
|
|
new Cartesian3(-12446.0, 12445.0, 12445.0),
|
|
];
|
|
var boundingSphere = BoundingSphere.fromPoints(positions);
|
|
|
|
var vertices = [];
|
|
for (var i = 0; i < positions.length; ++i) {
|
|
var position = positions[i];
|
|
vertices.push(position.x);
|
|
vertices.push(position.y);
|
|
vertices.push(position.z);
|
|
vertices.push(1.0);
|
|
vertices.push(2.0);
|
|
vertices.push(3.0);
|
|
vertices.push(4.0);
|
|
}
|
|
|
|
ellipsoidalOccluder.computeHorizonCullingPointFromVertices(
|
|
boundingSphere.center,
|
|
vertices,
|
|
7
|
|
);
|
|
|
|
expect(function () {
|
|
ellipsoidalOccluder.computeHorizonCullingPointFromVertices(
|
|
undefined,
|
|
vertices,
|
|
7
|
|
);
|
|
}).toThrowDeveloperError();
|
|
|
|
expect(function () {
|
|
ellipsoidalOccluder.computeHorizonCullingPointFromVertices(
|
|
boundingSphere.center,
|
|
undefined,
|
|
7
|
|
);
|
|
}).toThrowDeveloperError();
|
|
|
|
expect(function () {
|
|
ellipsoidalOccluder.computeHorizonCullingPointFromVertices(
|
|
boundingSphere.center,
|
|
vertices,
|
|
undefined
|
|
);
|
|
}).toThrowDeveloperError();
|
|
});
|
|
|
|
it("produces same answers as computeHorizonCullingPoint", function () {
|
|
var ellipsoid = new Ellipsoid(12345.0, 12345.0, 12345.0);
|
|
var ellipsoidalOccluder = new EllipsoidalOccluder(ellipsoid);
|
|
|
|
var positions = [
|
|
new Cartesian3(-12345.0, 12345.0, 12345.0),
|
|
new Cartesian3(-12346.0, 12345.0, 12345.0),
|
|
new Cartesian3(-12446.0, 12445.0, 12445.0),
|
|
];
|
|
var boundingSphere = BoundingSphere.fromPoints(positions);
|
|
|
|
var center = new Cartesian3(-12000.0, 12000.0, 12000.0);
|
|
|
|
var vertices = [];
|
|
for (var i = 0; i < positions.length; ++i) {
|
|
var position = positions[i];
|
|
vertices.push(position.x - center.x);
|
|
vertices.push(position.y - center.y);
|
|
vertices.push(position.z - center.z);
|
|
vertices.push(1.0);
|
|
vertices.push(2.0);
|
|
vertices.push(3.0);
|
|
vertices.push(4.0);
|
|
}
|
|
|
|
var result1 = ellipsoidalOccluder.computeHorizonCullingPoint(
|
|
boundingSphere.center,
|
|
positions
|
|
);
|
|
var result2 = ellipsoidalOccluder.computeHorizonCullingPointFromVertices(
|
|
boundingSphere.center,
|
|
vertices,
|
|
7,
|
|
center
|
|
);
|
|
|
|
expect(result1.x).toEqualEpsilon(result2.x, CesiumMath.EPSILON14);
|
|
expect(result1.y).toEqualEpsilon(result2.y, CesiumMath.EPSILON14);
|
|
expect(result1.z).toEqualEpsilon(result2.z, CesiumMath.EPSILON14);
|
|
});
|
|
|
|
it("computes a point under the ellipsoid with computeHorizonCullingPointFromVerticesPossiblyUnderEllipsoid", function () {
|
|
var ellipsoid = new Ellipsoid(12345.0, 4567.0, 8910.0);
|
|
var ellipsoidalOccluder = new EllipsoidalOccluder(ellipsoid);
|
|
var vertices = [12344.0, 0.0, 0.0];
|
|
var directionToPoint = new Cartesian3(1.0, 0.0, 0.0);
|
|
var center = Cartesian3.ZERO;
|
|
|
|
var result = ellipsoidalOccluder.computeHorizonCullingPointFromVerticesPossiblyUnderEllipsoid(
|
|
directionToPoint,
|
|
vertices,
|
|
3,
|
|
center,
|
|
-1.0
|
|
);
|
|
|
|
expect(result.x).toEqualEpsilon(1.0, CesiumMath.EPSILON14);
|
|
expect(result.y).toEqualEpsilon(0.0, CesiumMath.EPSILON14);
|
|
expect(result.z).toEqualEpsilon(0.0, CesiumMath.EPSILON14);
|
|
});
|
|
});
|
|
|
|
describe("computeHorizonCullingPointFromRectangle", function () {
|
|
it("returns undefined for global rectangle", function () {
|
|
var ellipsoid = new Ellipsoid(12345.0, 12345.0, 12345.0);
|
|
var ellipsoidalOccluder = new EllipsoidalOccluder(ellipsoid);
|
|
var rectangle = Rectangle.MAX_VALUE;
|
|
var result = ellipsoidalOccluder.computeHorizonCullingPointFromRectangle(
|
|
rectangle,
|
|
ellipsoid
|
|
);
|
|
expect(result).toBeUndefined();
|
|
});
|
|
|
|
it("computes a point with a grazing altitude close to zero for one of the rectangle corners and less than or equal to zero for the others", function () {
|
|
var ellipsoid = new Ellipsoid(12345.0, 12345.0, 12345.0);
|
|
var ellipsoidalOccluder = new EllipsoidalOccluder(ellipsoid);
|
|
|
|
var rectangle = new Rectangle(0.1, 0.2, 0.3, 0.4);
|
|
var result = ellipsoidalOccluder.computeHorizonCullingPointFromRectangle(
|
|
rectangle,
|
|
ellipsoid
|
|
);
|
|
expect(result).toBeDefined();
|
|
var unscaledResult = Cartesian3.multiplyComponents(
|
|
result,
|
|
ellipsoid.radii,
|
|
new Cartesian3()
|
|
);
|
|
|
|
// The grazing altitude of the ray from the horizon culling point to the
|
|
// position used to compute it should be very nearly zero.
|
|
var positions = [
|
|
ellipsoid.cartographicToCartesian(Rectangle.southwest(rectangle)),
|
|
ellipsoid.cartographicToCartesian(Rectangle.southeast(rectangle)),
|
|
ellipsoid.cartographicToCartesian(Rectangle.northwest(rectangle)),
|
|
ellipsoid.cartographicToCartesian(Rectangle.northeast(rectangle)),
|
|
];
|
|
|
|
var foundOneNearZero = false;
|
|
for (var i = 0; i < positions.length; ++i) {
|
|
var direction = Cartesian3.normalize(
|
|
Cartesian3.subtract(positions[i], unscaledResult, new Cartesian3()),
|
|
new Cartesian3()
|
|
);
|
|
var nearest = IntersectionTests.grazingAltitudeLocation(
|
|
new Ray(unscaledResult, direction),
|
|
ellipsoid
|
|
);
|
|
var nearestCartographic = ellipsoid.cartesianToCartographic(nearest);
|
|
if (Math.abs(nearestCartographic.height) < CesiumMath.EPSILON5) {
|
|
foundOneNearZero = true;
|
|
} else {
|
|
expect(nearestCartographic.height).toBeLessThanOrEqualTo(0.0);
|
|
}
|
|
}
|
|
|
|
expect(foundOneNearZero).toBe(true);
|
|
});
|
|
});
|
|
});
|