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

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);
});
});
});