cesium-native/CesiumGeospatial/test/TestS2CellBoundingVolume.cpp

151 lines
4.7 KiB
C++
Raw Normal View History

2024-12-21 00:56:49 +08:00
#include <CesiumGeometry/CullingResult.h>
#include <CesiumGeometry/Plane.h>
2024-12-21 01:00:09 +08:00
#include <CesiumGeospatial/Ellipsoid.h>
#include <CesiumGeospatial/S2CellBoundingVolume.h>
#include <CesiumGeospatial/S2CellID.h>
2024-12-21 00:56:49 +08:00
#include <CesiumUtility/Math.h>
2021-11-04 20:58:58 +08:00
2025-01-16 05:58:03 +08:00
#include <doctest/doctest.h>
2024-12-18 06:27:03 +08:00
#include <glm/exponential.hpp>
#include <glm/ext/vector_double3.hpp>
#include <span>
2021-11-04 20:58:58 +08:00
2021-11-05 11:49:11 +08:00
using namespace CesiumGeometry;
2021-11-04 20:58:58 +08:00
using namespace CesiumGeospatial;
2021-11-05 11:49:11 +08:00
using namespace CesiumUtility;
2021-11-04 20:58:58 +08:00
TEST_CASE("S2CellBoundingVolume") {
S2CellBoundingVolume tileS2Cell(
S2CellID::fromToken("1"),
0.0,
100000.0,
Ellipsoid::WGS84);
2021-11-05 12:40:30 +08:00
2025-01-16 05:58:03 +08:00
SUBCASE("distance-squared to position is 0 when camera is inside bounding "
2021-11-05 11:49:11 +08:00
"volume") {
2021-11-05 12:40:30 +08:00
CHECK(
tileS2Cell.computeDistanceSquaredToPosition(tileS2Cell.getCenter()) ==
0.0);
2021-11-05 11:49:11 +08:00
}
2025-01-16 05:58:03 +08:00
SUBCASE(
2021-11-05 12:40:30 +08:00
"Case I - distanceToCamera works when camera is facing only one plane") {
const double testDistance = 100.0;
2021-11-05 11:49:11 +08:00
std::span<const Plane> bvPlanes = tileS2Cell.getBoundingPlanes();
2021-11-05 11:49:11 +08:00
// Test against the top plane.
Plane topPlane(
bvPlanes[0].getNormal(),
bvPlanes[0].getDistance() - testDistance);
glm::dvec3 position =
topPlane.projectPointOntoPlane(tileS2Cell.getCenter());
CHECK(Math::equalsEpsilon(
glm::sqrt(tileS2Cell.computeDistanceSquaredToPosition(position)),
testDistance,
0.0,
2022-01-25 16:36:10 +08:00
Math::Epsilon7));
2021-11-05 11:49:11 +08:00
// Test against the first side plane.
Plane sidePlane0(
bvPlanes[2].getNormal(),
bvPlanes[2].getDistance() - testDistance);
std::span<const glm::dvec3> vertices = tileS2Cell.getVertices();
2021-11-05 11:49:11 +08:00
glm::dvec3 faceCenter = ((vertices[0] + vertices[1]) * 0.5 +
(vertices[4] + vertices[5]) * 0.5) *
0.5;
position = sidePlane0.projectPointOntoPlane(faceCenter);
CHECK(Math::equalsEpsilon(
glm::sqrt(tileS2Cell.computeDistanceSquaredToPosition(position)),
testDistance,
0.0,
2022-01-25 16:36:10 +08:00
Math::Epsilon7));
2021-11-05 11:49:11 +08:00
}
2021-11-05 12:40:30 +08:00
2025-01-16 05:58:03 +08:00
SUBCASE("Case II - distanceToCamera works when camera is facing two planes") {
2021-11-05 12:40:30 +08:00
const double testDistance = 5.0;
// Test with the top plane and the first side plane.
glm::dvec3 position =
(tileS2Cell.getVertices()[0] + tileS2Cell.getVertices()[1]) * 0.5;
position.z -= testDistance;
CHECK(Math::equalsEpsilon(
glm::sqrt(tileS2Cell.computeDistanceSquaredToPosition(position)),
testDistance,
0.0,
2022-01-25 16:36:10 +08:00
Math::Epsilon7));
2021-11-05 12:40:30 +08:00
// Test with first and second side planes.
position =
(tileS2Cell.getVertices()[0] + tileS2Cell.getVertices()[4]) * 0.5;
position.x -= 1;
position.z -= 1;
CHECK(Math::equalsEpsilon(
tileS2Cell.computeDistanceSquaredToPosition(position),
2.0,
0.0,
2022-01-25 16:36:10 +08:00
Math::Epsilon7));
2021-11-05 12:40:30 +08:00
// Test with bottom plane and second side plane. Handles the obtuse dihedral
// angle case.
position =
(tileS2Cell.getVertices()[5] + tileS2Cell.getVertices()[6]) * 0.5;
position.x -= 10000;
position.y -= 1;
CHECK(Math::equalsEpsilon(
glm::sqrt(tileS2Cell.computeDistanceSquaredToPosition(position)),
10000.0,
0.0,
2022-01-25 16:36:10 +08:00
Math::Epsilon7));
2021-11-05 12:40:30 +08:00
}
2025-01-16 05:58:03 +08:00
SUBCASE(
2021-11-05 12:40:30 +08:00
"Case III - distanceToCamera works when camera is facing three planes") {
glm::dvec3 position = tileS2Cell.getVertices()[2] + glm::dvec3(1.0);
CHECK(Math::equalsEpsilon(
tileS2Cell.computeDistanceSquaredToPosition(position),
3.0,
0.0,
2022-01-25 16:36:10 +08:00
Math::Epsilon7));
2021-11-05 12:40:30 +08:00
}
2025-01-16 05:58:03 +08:00
SUBCASE("Case IV - distanceToCamera works when camera is facing more than "
2021-11-05 12:40:30 +08:00
"three planes") {
glm::dvec3 position(-Ellipsoid::WGS84.getMaximumRadius(), 0.0, 0.0);
CHECK(Math::equalsEpsilon(
glm::sqrt(tileS2Cell.computeDistanceSquaredToPosition(position)),
Ellipsoid::WGS84.getMaximumRadius() +
tileS2Cell.getBoundingPlanes()[1].getDistance(),
0.0,
2022-01-25 16:36:10 +08:00
Math::Epsilon7));
2021-11-05 12:40:30 +08:00
}
2025-01-16 05:58:03 +08:00
SUBCASE("intersect plane") {
2021-11-05 12:40:30 +08:00
CHECK(
tileS2Cell.intersectPlane(Plane::ORIGIN_ZX_PLANE) ==
CullingResult::Intersecting);
Plane outsidePlane(
Plane::ORIGIN_YZ_PLANE.getNormal(),
Plane::ORIGIN_YZ_PLANE.getDistance() -
2 * Ellipsoid::WGS84.getMaximumRadius());
CHECK(tileS2Cell.intersectPlane(outsidePlane) == CullingResult::Outside);
CHECK(
tileS2Cell.intersectPlane(Plane::ORIGIN_YZ_PLANE) ==
CullingResult::Inside);
}
2025-01-16 05:58:03 +08:00
SUBCASE("can construct face 2 (North pole)") {
S2CellBoundingVolume face2Root(
S2CellID::fromToken("5"),
1000.0,
2000.0,
Ellipsoid::WGS84);
CHECK(face2Root.getCellID().isValid());
CHECK(face2Root.getCellID().getID() == 5764607523034234880U);
}
2021-11-04 20:58:58 +08:00
}