1022 lines
37 KiB
C++
1022 lines
37 KiB
C++
#include <Cesium3DTiles/BoundingVolume.h>
|
|
#include <Cesium3DTilesContent/ImplicitTilingUtilities.h>
|
|
#include <Cesium3DTilesContent/TileBoundingVolumes.h>
|
|
#include <CesiumGeometry/OctreeTileID.h>
|
|
#include <CesiumGeometry/OrientedBoundingBox.h>
|
|
#include <CesiumGeometry/QuadtreeTileID.h>
|
|
#include <CesiumGeometry/Transforms.h>
|
|
#include <CesiumGeospatial/BoundingRegion.h>
|
|
#include <CesiumGeospatial/Ellipsoid.h>
|
|
#include <CesiumGeospatial/S2CellBoundingVolume.h>
|
|
#include <CesiumGeospatial/S2CellID.h>
|
|
|
|
#include <doctest/doctest.h>
|
|
#include <glm/ext/matrix_double3x3.hpp>
|
|
#include <libmorton/morton.h>
|
|
|
|
#include <algorithm>
|
|
#include <optional>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
using namespace Cesium3DTiles;
|
|
using namespace Cesium3DTilesContent;
|
|
using namespace CesiumGeometry;
|
|
using namespace CesiumGeospatial;
|
|
|
|
TEST_CASE("ImplicitTilingUtilities child tile iteration") {
|
|
SUBCASE("QuadtreeTileID") {
|
|
QuadtreeTileID parent(11, 2, 3);
|
|
|
|
QuadtreeChildren children = ImplicitTilingUtilities::getChildren(parent);
|
|
|
|
// Check we can enumerate the children with a range-based for loop.
|
|
int count = 0;
|
|
for (const QuadtreeTileID& tileID : children) {
|
|
CHECK(tileID.level == 12);
|
|
CHECK((tileID.x == 4 || tileID.x == 5));
|
|
CHECK((tileID.y == 6 || tileID.y == 7));
|
|
++count;
|
|
}
|
|
|
|
CHECK(count == 4);
|
|
|
|
// Check we have exactly the right children.
|
|
std::vector<QuadtreeTileID> expected{
|
|
QuadtreeTileID(12, 4, 6),
|
|
QuadtreeTileID(12, 5, 6),
|
|
QuadtreeTileID(12, 4, 7),
|
|
QuadtreeTileID(12, 5, 7)};
|
|
auto mismatch = std::mismatch(
|
|
children.begin(),
|
|
children.end(),
|
|
expected.begin(),
|
|
expected.end());
|
|
CHECK(mismatch.first == children.end());
|
|
CHECK(mismatch.second == expected.end());
|
|
}
|
|
|
|
SUBCASE("OctreeTileID") {
|
|
OctreeTileID parent(11, 2, 3, 4);
|
|
|
|
OctreeChildren children = ImplicitTilingUtilities::getChildren(parent);
|
|
|
|
// Check we can enumerate the children with a range-based for loop.
|
|
int count = 0;
|
|
for (const OctreeTileID& tileID : children) {
|
|
CHECK(tileID.level == 12);
|
|
CHECK((tileID.x == 4 || tileID.x == 5));
|
|
CHECK((tileID.y == 6 || tileID.y == 7));
|
|
CHECK((tileID.z == 8 || tileID.z == 9));
|
|
++count;
|
|
}
|
|
|
|
CHECK(count == 8);
|
|
|
|
// Check we have exactly the right children.
|
|
std::vector<OctreeTileID> expected{
|
|
OctreeTileID(12, 4, 6, 8),
|
|
OctreeTileID(12, 5, 6, 8),
|
|
OctreeTileID(12, 4, 7, 8),
|
|
OctreeTileID(12, 5, 7, 8),
|
|
OctreeTileID(12, 4, 6, 9),
|
|
OctreeTileID(12, 5, 6, 9),
|
|
OctreeTileID(12, 4, 7, 9),
|
|
OctreeTileID(12, 5, 7, 9)};
|
|
auto mismatch = std::mismatch(
|
|
children.begin(),
|
|
children.end(),
|
|
expected.begin(),
|
|
expected.end());
|
|
CHECK(mismatch.first == children.end());
|
|
CHECK(mismatch.second == expected.end());
|
|
}
|
|
}
|
|
|
|
TEST_CASE("ImplicitTilingUtilities::resolveUrl") {
|
|
SUBCASE("quadtree") {
|
|
QuadtreeTileID tileID(11, 2, 3);
|
|
std::string url = ImplicitTilingUtilities::resolveUrl(
|
|
"https://example.com",
|
|
"tiles/{level}/{x}/{y}",
|
|
tileID);
|
|
CHECK(url == "https://example.com/tiles/11/2/3");
|
|
}
|
|
|
|
SUBCASE("octree") {
|
|
OctreeTileID tileID(11, 2, 3, 4);
|
|
std::string url = ImplicitTilingUtilities::resolveUrl(
|
|
"https://example.com",
|
|
"tiles/{level}/{x}/{y}/{z}",
|
|
tileID);
|
|
CHECK(url == "https://example.com/tiles/11/2/3/4");
|
|
}
|
|
}
|
|
|
|
TEST_CASE("ImplicitTilingUtilities::computeMortonIndex") {
|
|
SUBCASE("quadtree") {
|
|
QuadtreeTileID tileID(11, 2, 3);
|
|
CHECK(
|
|
ImplicitTilingUtilities::computeMortonIndex(tileID) ==
|
|
libmorton::morton2D_64_encode(2, 3));
|
|
}
|
|
|
|
SUBCASE("quadtree") {
|
|
OctreeTileID tileID(11, 2, 3, 4);
|
|
CHECK(
|
|
ImplicitTilingUtilities::computeMortonIndex(tileID) ==
|
|
libmorton::morton3D_64_encode(2, 3, 4));
|
|
}
|
|
}
|
|
|
|
TEST_CASE("ImplicitTilingUtilities::computeRelativeMortonIndex") {
|
|
SUBCASE("quadtree") {
|
|
QuadtreeTileID rootID(11, 2, 3);
|
|
QuadtreeTileID tileID(12, 5, 6);
|
|
CHECK(
|
|
ImplicitTilingUtilities::computeRelativeMortonIndex(rootID, tileID) ==
|
|
1);
|
|
}
|
|
|
|
SUBCASE("octree") {
|
|
OctreeTileID rootID(11, 2, 3, 4);
|
|
OctreeTileID tileID(12, 5, 6, 8);
|
|
CHECK(
|
|
ImplicitTilingUtilities::computeRelativeMortonIndex(rootID, tileID) ==
|
|
1);
|
|
}
|
|
}
|
|
|
|
TEST_CASE("ImplicitTilingUtilities::getParentID") {
|
|
SUBCASE("quadtree") {
|
|
QuadtreeTileID tileID(2, 1, 2);
|
|
std::optional<QuadtreeTileID> maybeParent =
|
|
ImplicitTilingUtilities::getParentID(tileID);
|
|
REQUIRE_UNARY(maybeParent);
|
|
CHECK_EQ(maybeParent, QuadtreeTileID(1, 0, 1));
|
|
|
|
std::optional<QuadtreeTileID> maybeGrandparent =
|
|
ImplicitTilingUtilities::getParentID(*maybeParent);
|
|
REQUIRE_UNARY(maybeGrandparent);
|
|
CHECK_EQ(maybeGrandparent, QuadtreeTileID(0, 0, 0));
|
|
|
|
CHECK_UNARY_FALSE(ImplicitTilingUtilities::getParentID(*maybeGrandparent));
|
|
}
|
|
|
|
SUBCASE("octree") {
|
|
OctreeTileID tileID(2, 3, 1, 2);
|
|
std::optional<OctreeTileID> maybeParent =
|
|
ImplicitTilingUtilities::getParentID(tileID);
|
|
REQUIRE_UNARY(maybeParent);
|
|
CHECK_EQ(maybeParent, OctreeTileID(1, 1, 0, 1));
|
|
|
|
std::optional<OctreeTileID> maybeGrandparent =
|
|
ImplicitTilingUtilities::getParentID(*maybeParent);
|
|
REQUIRE_UNARY(maybeGrandparent);
|
|
CHECK_EQ(maybeGrandparent, OctreeTileID(0, 0, 0, 0));
|
|
|
|
CHECK_UNARY_FALSE(ImplicitTilingUtilities::getParentID(*maybeGrandparent));
|
|
}
|
|
}
|
|
|
|
TEST_CASE("ImplicitTilingUtilities::getSubtreeRootID") {
|
|
SUBCASE("quadtree") {
|
|
QuadtreeTileID tileID(10, 2, 3);
|
|
CHECK(
|
|
ImplicitTilingUtilities::getSubtreeRootID(5, tileID) ==
|
|
QuadtreeTileID(10, 2, 3));
|
|
CHECK(
|
|
ImplicitTilingUtilities::getSubtreeRootID(4, tileID) ==
|
|
QuadtreeTileID(8, 0, 0));
|
|
}
|
|
|
|
SUBCASE("octree") {
|
|
OctreeTileID tileID(10, 2, 3, 4);
|
|
CHECK(
|
|
ImplicitTilingUtilities::getSubtreeRootID(5, tileID) ==
|
|
OctreeTileID(10, 2, 3, 4));
|
|
CHECK(
|
|
ImplicitTilingUtilities::getSubtreeRootID(4, tileID) ==
|
|
OctreeTileID(8, 0, 0, 1));
|
|
}
|
|
}
|
|
|
|
TEST_CASE("ImplicitTilingUtilities::absoluteTileIDToRelative") {
|
|
SUBCASE("quadtree") {
|
|
CHECK(
|
|
ImplicitTilingUtilities::absoluteTileIDToRelative(
|
|
QuadtreeTileID(0, 0, 0),
|
|
QuadtreeTileID(11, 2, 3)) == QuadtreeTileID(11, 2, 3));
|
|
CHECK(
|
|
ImplicitTilingUtilities::absoluteTileIDToRelative(
|
|
QuadtreeTileID(11, 2, 3),
|
|
QuadtreeTileID(11, 2, 3)) == QuadtreeTileID(0, 0, 0));
|
|
CHECK(
|
|
ImplicitTilingUtilities::absoluteTileIDToRelative(
|
|
QuadtreeTileID(11, 2, 3),
|
|
QuadtreeTileID(12, 5, 7)) == QuadtreeTileID(1, 1, 1));
|
|
}
|
|
|
|
SUBCASE("octree") {
|
|
CHECK(
|
|
ImplicitTilingUtilities::absoluteTileIDToRelative(
|
|
OctreeTileID(0, 0, 0, 0),
|
|
OctreeTileID(11, 2, 3, 4)) == OctreeTileID(11, 2, 3, 4));
|
|
CHECK(
|
|
ImplicitTilingUtilities::absoluteTileIDToRelative(
|
|
OctreeTileID(11, 2, 3, 4),
|
|
OctreeTileID(11, 2, 3, 4)) == OctreeTileID(0, 0, 0, 0));
|
|
CHECK(
|
|
ImplicitTilingUtilities::absoluteTileIDToRelative(
|
|
OctreeTileID(11, 2, 3, 4),
|
|
OctreeTileID(12, 5, 7, 9)) == OctreeTileID(1, 1, 1, 1));
|
|
}
|
|
}
|
|
|
|
TEST_CASE("ImplicitTilingUtilities::computeLevelDenominator") {
|
|
CHECK(ImplicitTilingUtilities::computeLevelDenominator(0) == 1.0);
|
|
CHECK(ImplicitTilingUtilities::computeLevelDenominator(1) == 2.0);
|
|
CHECK(ImplicitTilingUtilities::computeLevelDenominator(2) == 4.0);
|
|
}
|
|
|
|
TEST_CASE("ImplicitTilingUtilities::computeBoundingVolume") {
|
|
SUBCASE("OrientedBoundingBox") {
|
|
SUBCASE("quadtree") {
|
|
OrientedBoundingBox root(glm::dvec3(1.0, 2.0, 3.0), glm::dmat3(10.0));
|
|
|
|
OrientedBoundingBox l1x0y0 =
|
|
ImplicitTilingUtilities::computeBoundingVolume(
|
|
root,
|
|
QuadtreeTileID(1, 0, 0));
|
|
CHECK(l1x0y0.getCenter() == glm::dvec3(-4.0, -3.0, 3.0));
|
|
CHECK(l1x0y0.getLengths() == glm::dvec3(10.0, 10.0, 20.0));
|
|
|
|
OrientedBoundingBox l1x1y0 =
|
|
ImplicitTilingUtilities::computeBoundingVolume(
|
|
root,
|
|
QuadtreeTileID(1, 1, 0));
|
|
CHECK(l1x1y0.getCenter() == glm::dvec3(6.0, -3.0, 3.0));
|
|
CHECK(l1x1y0.getLengths() == glm::dvec3(10.0, 10.0, 20.0));
|
|
|
|
OrientedBoundingBox l1x0y1 =
|
|
ImplicitTilingUtilities::computeBoundingVolume(
|
|
root,
|
|
QuadtreeTileID(1, 0, 1));
|
|
CHECK(l1x0y1.getCenter() == glm::dvec3(-4.0, 7.0, 3.0));
|
|
CHECK(l1x0y1.getLengths() == glm::dvec3(10.0, 10.0, 20.0));
|
|
}
|
|
|
|
SUBCASE("octree") {
|
|
OrientedBoundingBox root(glm::dvec3(1.0, 2.0, 3.0), glm::dmat3(10.0));
|
|
|
|
OrientedBoundingBox l1x0y0z0 =
|
|
ImplicitTilingUtilities::computeBoundingVolume(
|
|
root,
|
|
OctreeTileID(1, 0, 0, 0));
|
|
CHECK(l1x0y0z0.getCenter() == glm::dvec3(-4.0, -3.0, -2.0));
|
|
CHECK(l1x0y0z0.getLengths() == glm::dvec3(10.0, 10.0, 10.0));
|
|
|
|
OrientedBoundingBox l1x1y0z0 =
|
|
ImplicitTilingUtilities::computeBoundingVolume(
|
|
root,
|
|
OctreeTileID(1, 1, 0, 0));
|
|
CHECK(l1x1y0z0.getCenter() == glm::dvec3(6.0, -3.0, -2.0));
|
|
CHECK(l1x1y0z0.getLengths() == glm::dvec3(10.0, 10.0, 10.0));
|
|
|
|
OrientedBoundingBox l1x0y1z0 =
|
|
ImplicitTilingUtilities::computeBoundingVolume(
|
|
root,
|
|
OctreeTileID(1, 0, 1, 0));
|
|
CHECK(l1x0y1z0.getCenter() == glm::dvec3(-4.0, 7.0, -2.0));
|
|
CHECK(l1x0y1z0.getLengths() == glm::dvec3(10.0, 10.0, 10.0));
|
|
|
|
OrientedBoundingBox l1x0y0z1 =
|
|
ImplicitTilingUtilities::computeBoundingVolume(
|
|
root,
|
|
OctreeTileID(1, 0, 0, 1));
|
|
CHECK(l1x0y0z1.getCenter() == glm::dvec3(-4.0, -3.0, 8.0));
|
|
CHECK(l1x0y0z1.getLengths() == glm::dvec3(10.0, 10.0, 10.0));
|
|
}
|
|
}
|
|
|
|
SUBCASE("BoundingRegion") {
|
|
SUBCASE("quadtree") {
|
|
BoundingRegion root(
|
|
GlobeRectangle(1.0, 2.0, 3.0, 4.0),
|
|
10.0,
|
|
20.0,
|
|
Ellipsoid::WGS84);
|
|
|
|
BoundingRegion l1x0y0 = ImplicitTilingUtilities::computeBoundingVolume(
|
|
root,
|
|
QuadtreeTileID(1, 0, 0),
|
|
Ellipsoid::WGS84);
|
|
CHECK(l1x0y0.getRectangle().getWest() == 1.0);
|
|
CHECK(l1x0y0.getRectangle().getSouth() == 2.0);
|
|
CHECK(l1x0y0.getRectangle().getEast() == 2.0);
|
|
CHECK(l1x0y0.getRectangle().getNorth() == 3.0);
|
|
CHECK(l1x0y0.getMinimumHeight() == 10.0);
|
|
CHECK(l1x0y0.getMaximumHeight() == 20.0);
|
|
|
|
BoundingRegion l1x1y0 = ImplicitTilingUtilities::computeBoundingVolume(
|
|
root,
|
|
QuadtreeTileID(1, 1, 0),
|
|
Ellipsoid::WGS84);
|
|
CHECK(l1x1y0.getRectangle().getWest() == 2.0);
|
|
CHECK(l1x1y0.getRectangle().getSouth() == 2.0);
|
|
CHECK(l1x1y0.getRectangle().getEast() == 3.0);
|
|
CHECK(l1x1y0.getRectangle().getNorth() == 3.0);
|
|
CHECK(l1x1y0.getMinimumHeight() == 10.0);
|
|
CHECK(l1x1y0.getMaximumHeight() == 20.0);
|
|
|
|
BoundingRegion l1x0y1 = ImplicitTilingUtilities::computeBoundingVolume(
|
|
root,
|
|
QuadtreeTileID(1, 0, 1),
|
|
Ellipsoid::WGS84);
|
|
CHECK(l1x0y1.getRectangle().getWest() == 1.0);
|
|
CHECK(l1x0y1.getRectangle().getSouth() == 3.0);
|
|
CHECK(l1x0y1.getRectangle().getEast() == 2.0);
|
|
CHECK(l1x0y1.getRectangle().getNorth() == 4.0);
|
|
CHECK(l1x0y1.getMinimumHeight() == 10.0);
|
|
CHECK(l1x0y1.getMaximumHeight() == 20.0);
|
|
}
|
|
|
|
SUBCASE("octree") {
|
|
BoundingRegion root(
|
|
GlobeRectangle(1.0, 2.0, 3.0, 4.0),
|
|
10.0,
|
|
20.0,
|
|
Ellipsoid::WGS84);
|
|
|
|
BoundingRegion l1x0y0z0 = ImplicitTilingUtilities::computeBoundingVolume(
|
|
root,
|
|
OctreeTileID(1, 0, 0, 0),
|
|
Ellipsoid::WGS84);
|
|
CHECK(l1x0y0z0.getRectangle().getWest() == 1.0);
|
|
CHECK(l1x0y0z0.getRectangle().getSouth() == 2.0);
|
|
CHECK(l1x0y0z0.getRectangle().getEast() == 2.0);
|
|
CHECK(l1x0y0z0.getRectangle().getNorth() == 3.0);
|
|
CHECK(l1x0y0z0.getMinimumHeight() == 10.0);
|
|
CHECK(l1x0y0z0.getMaximumHeight() == 15.0);
|
|
|
|
BoundingRegion l1x1y0z0 = ImplicitTilingUtilities::computeBoundingVolume(
|
|
root,
|
|
OctreeTileID(1, 1, 0, 0),
|
|
Ellipsoid::WGS84);
|
|
CHECK(l1x1y0z0.getRectangle().getWest() == 2.0);
|
|
CHECK(l1x1y0z0.getRectangle().getSouth() == 2.0);
|
|
CHECK(l1x1y0z0.getRectangle().getEast() == 3.0);
|
|
CHECK(l1x1y0z0.getRectangle().getNorth() == 3.0);
|
|
CHECK(l1x1y0z0.getMinimumHeight() == 10.0);
|
|
CHECK(l1x1y0z0.getMaximumHeight() == 15.0);
|
|
|
|
BoundingRegion l1x0y1z0 = ImplicitTilingUtilities::computeBoundingVolume(
|
|
root,
|
|
OctreeTileID(1, 0, 1, 0),
|
|
Ellipsoid::WGS84);
|
|
CHECK(l1x0y1z0.getRectangle().getWest() == 1.0);
|
|
CHECK(l1x0y1z0.getRectangle().getSouth() == 3.0);
|
|
CHECK(l1x0y1z0.getRectangle().getEast() == 2.0);
|
|
CHECK(l1x0y1z0.getRectangle().getNorth() == 4.0);
|
|
CHECK(l1x0y1z0.getMinimumHeight() == 10.0);
|
|
CHECK(l1x0y1z0.getMaximumHeight() == 15.0);
|
|
|
|
BoundingRegion l1x0y0z1 = ImplicitTilingUtilities::computeBoundingVolume(
|
|
root,
|
|
OctreeTileID(1, 0, 0, 1),
|
|
Ellipsoid::WGS84);
|
|
CHECK(l1x0y0z1.getRectangle().getWest() == 1.0);
|
|
CHECK(l1x0y0z1.getRectangle().getSouth() == 2.0);
|
|
CHECK(l1x0y0z1.getRectangle().getEast() == 2.0);
|
|
CHECK(l1x0y0z1.getRectangle().getNorth() == 3.0);
|
|
CHECK(l1x0y0z1.getMinimumHeight() == 15.0);
|
|
CHECK(l1x0y0z1.getMaximumHeight() == 20.0);
|
|
}
|
|
}
|
|
|
|
SUBCASE("S2") {
|
|
SUBCASE("quadtree") {
|
|
S2CellBoundingVolume root(
|
|
S2CellID::fromQuadtreeTileID(1, QuadtreeTileID(0, 0, 0)),
|
|
10.0,
|
|
20.0,
|
|
Ellipsoid::WGS84);
|
|
|
|
S2CellBoundingVolume l1x0y0 =
|
|
ImplicitTilingUtilities::computeBoundingVolume(
|
|
root,
|
|
QuadtreeTileID(1, 0, 0),
|
|
Ellipsoid::WGS84);
|
|
CHECK(l1x0y0.getCellID().getFace() == 1);
|
|
CHECK(
|
|
l1x0y0.getCellID().getID() ==
|
|
S2CellID::fromQuadtreeTileID(1, QuadtreeTileID(1, 0, 0)).getID());
|
|
CHECK(l1x0y0.getMinimumHeight() == 10.0);
|
|
CHECK(l1x0y0.getMaximumHeight() == 20.0);
|
|
|
|
S2CellBoundingVolume l1x1y0 =
|
|
ImplicitTilingUtilities::computeBoundingVolume(
|
|
root,
|
|
QuadtreeTileID(1, 1, 0),
|
|
Ellipsoid::WGS84);
|
|
CHECK(l1x1y0.getCellID().getFace() == 1);
|
|
CHECK(
|
|
l1x1y0.getCellID().getID() ==
|
|
S2CellID::fromQuadtreeTileID(1, QuadtreeTileID(1, 1, 0)).getID());
|
|
CHECK(l1x1y0.getMinimumHeight() == 10.0);
|
|
CHECK(l1x1y0.getMaximumHeight() == 20.0);
|
|
|
|
S2CellBoundingVolume l1x0y1 =
|
|
ImplicitTilingUtilities::computeBoundingVolume(
|
|
root,
|
|
QuadtreeTileID(1, 0, 1),
|
|
Ellipsoid::WGS84);
|
|
CHECK(l1x0y1.getCellID().getFace() == 1);
|
|
CHECK(
|
|
l1x0y1.getCellID().getID() ==
|
|
S2CellID::fromQuadtreeTileID(1, QuadtreeTileID(1, 0, 1)).getID());
|
|
CHECK(l1x0y1.getMinimumHeight() == 10.0);
|
|
CHECK(l1x0y1.getMaximumHeight() == 20.0);
|
|
}
|
|
|
|
SUBCASE("octree") {
|
|
S2CellBoundingVolume root(
|
|
S2CellID::fromQuadtreeTileID(1, QuadtreeTileID(0, 0, 0)),
|
|
10.0,
|
|
20.0,
|
|
Ellipsoid::WGS84);
|
|
|
|
S2CellBoundingVolume l1x0y0z0 =
|
|
ImplicitTilingUtilities::computeBoundingVolume(
|
|
root,
|
|
OctreeTileID(1, 0, 0, 0),
|
|
Ellipsoid::WGS84);
|
|
CHECK(l1x0y0z0.getCellID().getFace() == 1);
|
|
CHECK(
|
|
l1x0y0z0.getCellID().getID() ==
|
|
S2CellID::fromQuadtreeTileID(1, QuadtreeTileID(1, 0, 0)).getID());
|
|
CHECK(l1x0y0z0.getMinimumHeight() == 10.0);
|
|
CHECK(l1x0y0z0.getMaximumHeight() == 15.0);
|
|
|
|
S2CellBoundingVolume l1x1y0z0 =
|
|
ImplicitTilingUtilities::computeBoundingVolume(
|
|
root,
|
|
OctreeTileID(1, 1, 0, 0),
|
|
Ellipsoid::WGS84);
|
|
CHECK(l1x1y0z0.getCellID().getFace() == 1);
|
|
CHECK(
|
|
l1x1y0z0.getCellID().getID() ==
|
|
S2CellID::fromQuadtreeTileID(1, QuadtreeTileID(1, 1, 0)).getID());
|
|
CHECK(l1x1y0z0.getMinimumHeight() == 10.0);
|
|
CHECK(l1x1y0z0.getMaximumHeight() == 15.0);
|
|
|
|
S2CellBoundingVolume l1x0y1z0 =
|
|
ImplicitTilingUtilities::computeBoundingVolume(
|
|
root,
|
|
OctreeTileID(1, 0, 1, 0),
|
|
Ellipsoid::WGS84);
|
|
CHECK(l1x0y1z0.getCellID().getFace() == 1);
|
|
CHECK(
|
|
l1x0y1z0.getCellID().getID() ==
|
|
S2CellID::fromQuadtreeTileID(1, QuadtreeTileID(1, 0, 1)).getID());
|
|
CHECK(l1x0y1z0.getMinimumHeight() == 10.0);
|
|
CHECK(l1x0y1z0.getMaximumHeight() == 15.0);
|
|
|
|
S2CellBoundingVolume l1x0y0z1 =
|
|
ImplicitTilingUtilities::computeBoundingVolume(
|
|
root,
|
|
OctreeTileID(1, 0, 0, 1),
|
|
Ellipsoid::WGS84);
|
|
CHECK(l1x0y0z1.getCellID().getFace() == 1);
|
|
CHECK(
|
|
l1x0y0z1.getCellID().getID() ==
|
|
S2CellID::fromQuadtreeTileID(1, QuadtreeTileID(1, 0, 0)).getID());
|
|
CHECK(l1x0y0z1.getMinimumHeight() == 15.0);
|
|
CHECK(l1x0y0z1.getMaximumHeight() == 20.0);
|
|
}
|
|
}
|
|
|
|
SUBCASE("BoundingCylinderRegion (whole)") {
|
|
BoundingCylinderRegion root(
|
|
glm::dvec3(1.0, 2.0, 3.0),
|
|
glm::dquat(CesiumGeometry::Transforms::Z_UP_TO_Y_UP),
|
|
2.0,
|
|
glm::dvec2(0.0, 1.0));
|
|
|
|
SUBCASE("quadtree") {
|
|
BoundingCylinderRegion l1x0y0 =
|
|
ImplicitTilingUtilities::computeBoundingVolume(
|
|
root,
|
|
QuadtreeTileID(1, 0, 0));
|
|
|
|
CHECK(l1x0y0.getHeight() == root.getHeight());
|
|
CHECK(l1x0y0.getRadialBounds() == glm::dvec2(0.0, 0.5));
|
|
CHECK(
|
|
l1x0y0.getAngularBounds() ==
|
|
glm::dvec2(-CesiumUtility::Math::OnePi, 0.0));
|
|
CHECK(l1x0y0.getRotation() == root.getRotation());
|
|
CHECK(l1x0y0.getTranslation() == root.getTranslation());
|
|
|
|
BoundingCylinderRegion l1x1y0 =
|
|
ImplicitTilingUtilities::computeBoundingVolume(
|
|
root,
|
|
QuadtreeTileID(1, 1, 0));
|
|
|
|
CHECK(l1x1y0.getHeight() == root.getHeight());
|
|
CHECK(l1x1y0.getRadialBounds() == glm::dvec2(0.5, 1.0));
|
|
CHECK(
|
|
l1x1y0.getAngularBounds() ==
|
|
glm::dvec2(-CesiumUtility::Math::OnePi, 0.0));
|
|
CHECK(l1x1y0.getRotation() == root.getRotation());
|
|
CHECK(l1x1y0.getTranslation() == root.getTranslation());
|
|
|
|
BoundingCylinderRegion l1x0y1 =
|
|
ImplicitTilingUtilities::computeBoundingVolume(
|
|
root,
|
|
QuadtreeTileID(1, 0, 1));
|
|
CHECK(l1x0y1.getHeight() == root.getHeight());
|
|
CHECK(l1x0y1.getRadialBounds() == glm::dvec2(0.0, 0.5));
|
|
CHECK(
|
|
l1x0y1.getAngularBounds() ==
|
|
glm::dvec2(0.0, CesiumUtility::Math::OnePi));
|
|
CHECK(l1x0y1.getRotation() == root.getRotation());
|
|
CHECK(l1x0y1.getTranslation() == root.getTranslation());
|
|
}
|
|
|
|
SUBCASE("octree") {
|
|
double expectedHeight = 0.5 * root.getHeight();
|
|
|
|
BoundingCylinderRegion l1x0y0z0 =
|
|
ImplicitTilingUtilities::computeBoundingVolume(
|
|
root,
|
|
OctreeTileID(1, 0, 0, 0));
|
|
{
|
|
CHECK(l1x0y0z0.getHeight() == expectedHeight);
|
|
CHECK(l1x0y0z0.getRadialBounds() == glm::dvec2(0.0, 0.5));
|
|
CHECK(
|
|
l1x0y0z0.getAngularBounds() ==
|
|
glm::dvec2(-CesiumUtility::Math::OnePi, 0.0));
|
|
CHECK(l1x0y0z0.getRotation() == root.getRotation());
|
|
|
|
glm::dvec3 expectedTranslation =
|
|
root.getTranslation() + glm::dvec3(0.0, -0.5 * expectedHeight, 0.0);
|
|
CHECK(l1x0y0z0.getTranslation() == expectedTranslation);
|
|
}
|
|
|
|
BoundingCylinderRegion l1x1y0z0 =
|
|
ImplicitTilingUtilities::computeBoundingVolume(
|
|
root,
|
|
OctreeTileID(1, 1, 0, 0));
|
|
{
|
|
CHECK(l1x1y0z0.getHeight() == expectedHeight);
|
|
CHECK(l1x1y0z0.getRadialBounds() == glm::dvec2(0.5, 1.0));
|
|
CHECK(
|
|
l1x1y0z0.getAngularBounds() ==
|
|
glm::dvec2(-CesiumUtility::Math::OnePi, 0.0));
|
|
CHECK(l1x1y0z0.getRotation() == root.getRotation());
|
|
|
|
glm::dvec3 expectedTranslation =
|
|
root.getTranslation() + glm::dvec3(0.0, -0.5 * expectedHeight, 0.0);
|
|
CHECK(l1x1y0z0.getTranslation() == expectedTranslation);
|
|
}
|
|
|
|
BoundingCylinderRegion l1x0y1z0 =
|
|
ImplicitTilingUtilities::computeBoundingVolume(
|
|
root,
|
|
OctreeTileID(1, 0, 1, 0));
|
|
{
|
|
CHECK(l1x0y1z0.getHeight() == expectedHeight);
|
|
CHECK(l1x0y1z0.getRadialBounds() == glm::dvec2(0.0, 0.5));
|
|
CHECK(
|
|
l1x0y1z0.getAngularBounds() ==
|
|
glm::dvec2(0.0, CesiumUtility::Math::OnePi));
|
|
CHECK(l1x0y1z0.getRotation() == root.getRotation());
|
|
|
|
glm::dvec3 expectedTranslation =
|
|
root.getTranslation() + glm::dvec3(0.0, -0.5 * expectedHeight, 0.0);
|
|
CHECK(l1x0y1z0.getTranslation() == expectedTranslation);
|
|
}
|
|
|
|
BoundingCylinderRegion l1x0y0z1 =
|
|
ImplicitTilingUtilities::computeBoundingVolume(
|
|
root,
|
|
OctreeTileID(1, 0, 0, 1));
|
|
{
|
|
CHECK(l1x0y0z1.getHeight() == expectedHeight);
|
|
CHECK(l1x0y0z1.getRadialBounds() == glm::dvec2(0.0, 0.5));
|
|
CHECK(
|
|
l1x0y0z1.getAngularBounds() ==
|
|
glm::dvec2(-CesiumUtility::Math::OnePi, 0.0));
|
|
CHECK(l1x0y0z1.getRotation() == root.getRotation());
|
|
|
|
glm::dvec3 expectedTranslation =
|
|
root.getTranslation() + glm::dvec3(0.0, 0.5 * expectedHeight, 0.0);
|
|
CHECK(l1x0y0z1.getTranslation() == expectedTranslation);
|
|
}
|
|
}
|
|
}
|
|
|
|
SUBCASE("BoundingCylinderRegion (partial)") {
|
|
BoundingCylinderRegion root(
|
|
glm::dvec3(-1.0, 1.0, 2.0),
|
|
glm::dquat(1.0, 0.0, 0.0, 0.0),
|
|
2.0,
|
|
glm::dvec2(0.0, 1.0),
|
|
glm::dvec2(
|
|
-CesiumUtility::Math::PiOverTwo,
|
|
CesiumUtility::Math::PiOverTwo));
|
|
|
|
SUBCASE("quadtree") {
|
|
BoundingCylinderRegion l1x0y0 =
|
|
ImplicitTilingUtilities::computeBoundingVolume(
|
|
root,
|
|
QuadtreeTileID(1, 0, 0));
|
|
|
|
CHECK(l1x0y0.getHeight() == root.getHeight());
|
|
CHECK(l1x0y0.getRadialBounds() == glm::dvec2(0.0, 0.5));
|
|
CHECK(CesiumUtility::Math::equalsEpsilon(
|
|
l1x0y0.getAngularBounds(),
|
|
glm::dvec2(-CesiumUtility::Math::PiOverTwo, 0.0),
|
|
CesiumUtility::Math::Epsilon6));
|
|
CHECK(l1x0y0.getRotation() == root.getRotation());
|
|
CHECK(l1x0y0.getTranslation() == root.getTranslation());
|
|
|
|
BoundingCylinderRegion l1x1y0 =
|
|
ImplicitTilingUtilities::computeBoundingVolume(
|
|
root,
|
|
QuadtreeTileID(1, 1, 0));
|
|
|
|
CHECK(l1x1y0.getHeight() == root.getHeight());
|
|
CHECK(l1x1y0.getRadialBounds() == glm::dvec2(0.5, 1.0));
|
|
CHECK(CesiumUtility::Math::equalsEpsilon(
|
|
l1x0y0.getAngularBounds(),
|
|
glm::dvec2(-CesiumUtility::Math::PiOverTwo, 0.0),
|
|
CesiumUtility::Math::Epsilon6));
|
|
CHECK(l1x1y0.getRotation() == root.getRotation());
|
|
CHECK(l1x1y0.getTranslation() == root.getTranslation());
|
|
|
|
BoundingCylinderRegion l1x0y1 =
|
|
ImplicitTilingUtilities::computeBoundingVolume(
|
|
root,
|
|
QuadtreeTileID(1, 0, 1));
|
|
CHECK(l1x0y1.getHeight() == root.getHeight());
|
|
CHECK(l1x0y1.getRadialBounds() == glm::dvec2(0.0, 0.5));
|
|
CHECK(CesiumUtility::Math::equalsEpsilon(
|
|
l1x0y1.getAngularBounds(),
|
|
glm::dvec2(0.0, CesiumUtility::Math::PiOverTwo),
|
|
CesiumUtility::Math::Epsilon6));
|
|
CHECK(l1x0y1.getRotation() == root.getRotation());
|
|
CHECK(l1x0y1.getTranslation() == root.getTranslation());
|
|
}
|
|
|
|
SUBCASE("octree") {
|
|
double expectedHeight = 0.5 * root.getHeight();
|
|
|
|
BoundingCylinderRegion l1x0y0z0 =
|
|
ImplicitTilingUtilities::computeBoundingVolume(
|
|
root,
|
|
OctreeTileID(1, 0, 0, 0));
|
|
{
|
|
CHECK(l1x0y0z0.getHeight() == expectedHeight);
|
|
CHECK(l1x0y0z0.getRadialBounds() == glm::dvec2(0.0, 0.5));
|
|
CHECK(CesiumUtility::Math::equalsEpsilon(
|
|
l1x0y0z0.getAngularBounds(),
|
|
glm::dvec2(-CesiumUtility::Math::PiOverTwo, 0.0),
|
|
CesiumUtility::Math::Epsilon6));
|
|
CHECK(l1x0y0z0.getRotation() == root.getRotation());
|
|
|
|
glm::dvec3 expectedTranslation =
|
|
root.getTranslation() + glm::dvec3(0.0, 0.0, -0.5 * expectedHeight);
|
|
CHECK(l1x0y0z0.getTranslation() == expectedTranslation);
|
|
}
|
|
|
|
BoundingCylinderRegion l1x1y0z0 =
|
|
ImplicitTilingUtilities::computeBoundingVolume(
|
|
root,
|
|
OctreeTileID(1, 1, 0, 0));
|
|
{
|
|
CHECK(l1x1y0z0.getHeight() == expectedHeight);
|
|
CHECK(l1x1y0z0.getRadialBounds() == glm::dvec2(0.5, 1.0));
|
|
CHECK(CesiumUtility::Math::equalsEpsilon(
|
|
l1x1y0z0.getAngularBounds(),
|
|
glm::dvec2(-CesiumUtility::Math::PiOverTwo, 0.0),
|
|
CesiumUtility::Math::Epsilon6));
|
|
CHECK(l1x1y0z0.getRotation() == root.getRotation());
|
|
|
|
glm::dvec3 expectedTranslation =
|
|
root.getTranslation() + glm::dvec3(0.0, 0.0, -0.5 * expectedHeight);
|
|
CHECK(l1x1y0z0.getTranslation() == expectedTranslation);
|
|
}
|
|
|
|
BoundingCylinderRegion l1x0y1z0 =
|
|
ImplicitTilingUtilities::computeBoundingVolume(
|
|
root,
|
|
OctreeTileID(1, 0, 1, 0));
|
|
{
|
|
CHECK(l1x0y1z0.getHeight() == expectedHeight);
|
|
CHECK(l1x0y1z0.getRadialBounds() == glm::dvec2(0.0, 0.5));
|
|
CHECK(CesiumUtility::Math::equalsEpsilon(
|
|
l1x0y1z0.getAngularBounds(),
|
|
glm::dvec2(0.0, CesiumUtility::Math::PiOverTwo),
|
|
CesiumUtility::Math::Epsilon6));
|
|
CHECK(l1x0y1z0.getRotation() == root.getRotation());
|
|
|
|
glm::dvec3 expectedTranslation =
|
|
root.getTranslation() + glm::dvec3(0.0, 0.0, -0.5 * expectedHeight);
|
|
CHECK(l1x0y1z0.getTranslation() == expectedTranslation);
|
|
}
|
|
|
|
BoundingCylinderRegion l1x0y0z1 =
|
|
ImplicitTilingUtilities::computeBoundingVolume(
|
|
root,
|
|
OctreeTileID(1, 0, 0, 1));
|
|
{
|
|
CHECK(l1x0y0z1.getHeight() == expectedHeight);
|
|
CHECK(l1x0y0z1.getRadialBounds() == glm::dvec2(0.0, 0.5));
|
|
CHECK(CesiumUtility::Math::equalsEpsilon(
|
|
l1x0y0z1.getAngularBounds(),
|
|
glm::dvec2(-CesiumUtility::Math::PiOverTwo, 0.0),
|
|
CesiumUtility::Math::Epsilon6));
|
|
CHECK(l1x0y0z1.getRotation() == root.getRotation());
|
|
|
|
glm::dvec3 expectedTranslation =
|
|
root.getTranslation() + glm::dvec3(0.0, 0.0, 0.5 * expectedHeight);
|
|
CHECK(l1x0y0z1.getTranslation() == expectedTranslation);
|
|
}
|
|
}
|
|
}
|
|
|
|
SUBCASE("BoundingCylinderRegion (partial with discontinuity)") {
|
|
BoundingCylinderRegion root(
|
|
glm::dvec3(-1.0, 1.0, 2.0),
|
|
glm::dquat(1.0, 0.0, 0.0, 0.0),
|
|
2.0,
|
|
glm::dvec2(0.0, 1.0),
|
|
glm::dvec2(
|
|
CesiumUtility::Math::PiOverFour,
|
|
-CesiumUtility::Math::PiOverFour));
|
|
|
|
// The full angle range is 3pi / 2, and the implicit subdivision splits
|
|
// this range in half at the -pi / pi discontinuity line.
|
|
|
|
SUBCASE("quadtree") {
|
|
BoundingCylinderRegion l1x0y0 =
|
|
ImplicitTilingUtilities::computeBoundingVolume(
|
|
root,
|
|
QuadtreeTileID(1, 0, 0));
|
|
|
|
CHECK(l1x0y0.getHeight() == root.getHeight());
|
|
CHECK(l1x0y0.getRadialBounds() == glm::dvec2(0.0, 0.5));
|
|
CHECK(CesiumUtility::Math::equalsEpsilon(
|
|
l1x0y0.getAngularBounds(),
|
|
glm::dvec2(
|
|
CesiumUtility::Math::PiOverFour,
|
|
CesiumUtility::Math::OnePi),
|
|
CesiumUtility::Math::Epsilon6));
|
|
CHECK(l1x0y0.getRotation() == root.getRotation());
|
|
CHECK(l1x0y0.getTranslation() == root.getTranslation());
|
|
|
|
BoundingCylinderRegion l1x1y0 =
|
|
ImplicitTilingUtilities::computeBoundingVolume(
|
|
root,
|
|
QuadtreeTileID(1, 1, 0));
|
|
|
|
CHECK(l1x1y0.getHeight() == root.getHeight());
|
|
CHECK(l1x1y0.getRadialBounds() == glm::dvec2(0.5, 1.0));
|
|
CHECK(CesiumUtility::Math::equalsEpsilon(
|
|
l1x1y0.getAngularBounds(),
|
|
glm::dvec2(
|
|
CesiumUtility::Math::PiOverFour,
|
|
CesiumUtility::Math::OnePi),
|
|
CesiumUtility::Math::Epsilon6));
|
|
CHECK(l1x1y0.getRotation() == root.getRotation());
|
|
CHECK(l1x1y0.getTranslation() == root.getTranslation());
|
|
|
|
BoundingCylinderRegion l1x0y1 =
|
|
ImplicitTilingUtilities::computeBoundingVolume(
|
|
root,
|
|
QuadtreeTileID(1, 0, 1));
|
|
CHECK(l1x0y1.getHeight() == root.getHeight());
|
|
CHECK(l1x0y1.getRadialBounds() == glm::dvec2(0.0, 0.5));
|
|
CHECK(CesiumUtility::Math::equalsEpsilon(
|
|
l1x0y1.getAngularBounds(),
|
|
glm::dvec2(
|
|
-CesiumUtility::Math::OnePi,
|
|
-CesiumUtility::Math::PiOverFour),
|
|
CesiumUtility::Math::Epsilon6));
|
|
CHECK(l1x0y1.getRotation() == root.getRotation());
|
|
CHECK(l1x0y1.getTranslation() == root.getTranslation());
|
|
}
|
|
|
|
SUBCASE("octree") {
|
|
double expectedHeight = 0.5 * root.getHeight();
|
|
|
|
BoundingCylinderRegion l1x0y0z0 =
|
|
ImplicitTilingUtilities::computeBoundingVolume(
|
|
root,
|
|
OctreeTileID(1, 0, 0, 0));
|
|
{
|
|
CHECK(l1x0y0z0.getHeight() == expectedHeight);
|
|
CHECK(l1x0y0z0.getRadialBounds() == glm::dvec2(0.0, 0.5));
|
|
CHECK(CesiumUtility::Math::equalsEpsilon(
|
|
l1x0y0z0.getAngularBounds(),
|
|
glm::dvec2(
|
|
CesiumUtility::Math::PiOverFour,
|
|
CesiumUtility::Math::OnePi),
|
|
CesiumUtility::Math::Epsilon6));
|
|
CHECK(l1x0y0z0.getRotation() == root.getRotation());
|
|
|
|
glm::dvec3 expectedTranslation =
|
|
root.getTranslation() + glm::dvec3(0.0, 0.0, -0.5 * expectedHeight);
|
|
CHECK(l1x0y0z0.getTranslation() == expectedTranslation);
|
|
}
|
|
|
|
BoundingCylinderRegion l1x1y0z0 =
|
|
ImplicitTilingUtilities::computeBoundingVolume(
|
|
root,
|
|
OctreeTileID(1, 1, 0, 0));
|
|
{
|
|
CHECK(l1x1y0z0.getHeight() == expectedHeight);
|
|
CHECK(l1x1y0z0.getRadialBounds() == glm::dvec2(0.5, 1.0));
|
|
CHECK(CesiumUtility::Math::equalsEpsilon(
|
|
l1x1y0z0.getAngularBounds(),
|
|
glm::dvec2(
|
|
CesiumUtility::Math::PiOverFour,
|
|
CesiumUtility::Math::OnePi),
|
|
CesiumUtility::Math::Epsilon6));
|
|
CHECK(l1x1y0z0.getRotation() == root.getRotation());
|
|
|
|
glm::dvec3 expectedTranslation =
|
|
root.getTranslation() + glm::dvec3(0.0, 0.0, -0.5 * expectedHeight);
|
|
CHECK(l1x1y0z0.getTranslation() == expectedTranslation);
|
|
}
|
|
|
|
BoundingCylinderRegion l1x0y1z0 =
|
|
ImplicitTilingUtilities::computeBoundingVolume(
|
|
root,
|
|
OctreeTileID(1, 0, 1, 0));
|
|
{
|
|
CHECK(l1x0y1z0.getHeight() == expectedHeight);
|
|
CHECK(l1x0y1z0.getRadialBounds() == glm::dvec2(0.0, 0.5));
|
|
CHECK(CesiumUtility::Math::equalsEpsilon(
|
|
l1x0y1z0.getAngularBounds(),
|
|
glm::dvec2(
|
|
-CesiumUtility::Math::OnePi,
|
|
-CesiumUtility::Math::PiOverFour),
|
|
CesiumUtility::Math::Epsilon6));
|
|
CHECK(l1x0y1z0.getRotation() == root.getRotation());
|
|
|
|
glm::dvec3 expectedTranslation =
|
|
root.getTranslation() + glm::dvec3(0.0, 0.0, -0.5 * expectedHeight);
|
|
CHECK(l1x0y1z0.getTranslation() == expectedTranslation);
|
|
}
|
|
|
|
BoundingCylinderRegion l1x0y0z1 =
|
|
ImplicitTilingUtilities::computeBoundingVolume(
|
|
root,
|
|
OctreeTileID(1, 0, 0, 1));
|
|
{
|
|
CHECK(l1x0y0z1.getHeight() == expectedHeight);
|
|
CHECK(l1x0y0z1.getRadialBounds() == glm::dvec2(0.0, 0.5));
|
|
CHECK(CesiumUtility::Math::equalsEpsilon(
|
|
l1x0y0z1.getAngularBounds(),
|
|
glm::dvec2(
|
|
CesiumUtility::Math::PiOverFour,
|
|
CesiumUtility::Math::OnePi),
|
|
CesiumUtility::Math::Epsilon6));
|
|
CHECK(l1x0y0z1.getRotation() == root.getRotation());
|
|
|
|
glm::dvec3 expectedTranslation =
|
|
root.getTranslation() + glm::dvec3(0.0, 0.0, 0.5 * expectedHeight);
|
|
CHECK(l1x0y0z1.getTranslation() == expectedTranslation);
|
|
}
|
|
}
|
|
}
|
|
|
|
SUBCASE("BoundingVolume") {
|
|
SUBCASE("quadtree") {
|
|
BoundingVolume root{};
|
|
|
|
TileBoundingVolumes::setOrientedBoundingBox(
|
|
root,
|
|
OrientedBoundingBox(glm::dvec3(1.0, 2.0, 3.0), glm::dmat3(10.0)));
|
|
TileBoundingVolumes::setBoundingRegion(
|
|
root,
|
|
BoundingRegion(
|
|
GlobeRectangle(1.0, 2.0, 3.0, 4.0),
|
|
10.0,
|
|
20.0,
|
|
Ellipsoid::WGS84));
|
|
TileBoundingVolumes::setS2CellBoundingVolume(
|
|
root,
|
|
S2CellBoundingVolume(
|
|
S2CellID::fromQuadtreeTileID(1, QuadtreeTileID(0, 0, 0)),
|
|
10.0,
|
|
20.0,
|
|
Ellipsoid::WGS84));
|
|
|
|
BoundingVolume l1x0y0 = ImplicitTilingUtilities::computeBoundingVolume(
|
|
root,
|
|
QuadtreeTileID(1, 0, 0),
|
|
Ellipsoid::WGS84);
|
|
std::optional<OrientedBoundingBox> maybeBox =
|
|
TileBoundingVolumes::getOrientedBoundingBox(l1x0y0);
|
|
REQUIRE(maybeBox);
|
|
CHECK(maybeBox->getCenter() == glm::dvec3(-4.0, -3.0, 3.0));
|
|
CHECK(maybeBox->getLengths() == glm::dvec3(10.0, 10.0, 20.0));
|
|
|
|
BoundingVolume l1x1y0 = ImplicitTilingUtilities::computeBoundingVolume(
|
|
root,
|
|
QuadtreeTileID(1, 1, 0),
|
|
Ellipsoid::WGS84);
|
|
std::optional<BoundingRegion> maybeRegion =
|
|
TileBoundingVolumes::getBoundingRegion(l1x1y0, Ellipsoid::WGS84);
|
|
REQUIRE(maybeRegion);
|
|
CHECK(maybeRegion->getRectangle().getWest() == 2.0);
|
|
CHECK(maybeRegion->getRectangle().getSouth() == 2.0);
|
|
CHECK(maybeRegion->getRectangle().getEast() == 3.0);
|
|
CHECK(maybeRegion->getRectangle().getNorth() == 3.0);
|
|
CHECK(maybeRegion->getMinimumHeight() == 10.0);
|
|
CHECK(maybeRegion->getMaximumHeight() == 20.0);
|
|
|
|
BoundingVolume l1x0y1 = ImplicitTilingUtilities::computeBoundingVolume(
|
|
root,
|
|
QuadtreeTileID(1, 0, 1),
|
|
Ellipsoid::WGS84);
|
|
std::optional<S2CellBoundingVolume> maybeS2 =
|
|
TileBoundingVolumes::getS2CellBoundingVolume(
|
|
l1x0y1,
|
|
Ellipsoid::WGS84);
|
|
REQUIRE(maybeS2);
|
|
CHECK(maybeS2->getCellID().getFace() == 1);
|
|
CHECK(
|
|
maybeS2->getCellID().getID() ==
|
|
S2CellID::fromQuadtreeTileID(1, QuadtreeTileID(1, 0, 1)).getID());
|
|
CHECK(maybeS2->getMinimumHeight() == 10.0);
|
|
CHECK(maybeS2->getMaximumHeight() == 20.0);
|
|
}
|
|
|
|
SUBCASE("octree") {
|
|
BoundingVolume root{};
|
|
|
|
TileBoundingVolumes::setOrientedBoundingBox(
|
|
root,
|
|
OrientedBoundingBox(glm::dvec3(1.0, 2.0, 3.0), glm::dmat3(10.0)));
|
|
TileBoundingVolumes::setBoundingRegion(
|
|
root,
|
|
BoundingRegion(
|
|
GlobeRectangle(1.0, 2.0, 3.0, 4.0),
|
|
10.0,
|
|
20.0,
|
|
Ellipsoid::WGS84));
|
|
TileBoundingVolumes::setS2CellBoundingVolume(
|
|
root,
|
|
S2CellBoundingVolume(
|
|
S2CellID::fromQuadtreeTileID(1, QuadtreeTileID(0, 0, 0)),
|
|
10.0,
|
|
20.0,
|
|
Ellipsoid::WGS84));
|
|
|
|
BoundingVolume l1x0y0 = ImplicitTilingUtilities::computeBoundingVolume(
|
|
root,
|
|
OctreeTileID(1, 0, 0, 0),
|
|
Ellipsoid::WGS84);
|
|
std::optional<OrientedBoundingBox> maybeBox =
|
|
TileBoundingVolumes::getOrientedBoundingBox(l1x0y0);
|
|
REQUIRE(maybeBox);
|
|
CHECK(maybeBox->getCenter() == glm::dvec3(-4.0, -3.0, -2.0));
|
|
CHECK(maybeBox->getLengths() == glm::dvec3(10.0, 10.0, 10.0));
|
|
|
|
BoundingVolume l1x1y0 = ImplicitTilingUtilities::computeBoundingVolume(
|
|
root,
|
|
OctreeTileID(1, 1, 0, 0),
|
|
Ellipsoid::WGS84);
|
|
std::optional<BoundingRegion> maybeRegion =
|
|
TileBoundingVolumes::getBoundingRegion(l1x1y0, Ellipsoid::WGS84);
|
|
REQUIRE(maybeRegion);
|
|
CHECK(maybeRegion->getRectangle().getWest() == 2.0);
|
|
CHECK(maybeRegion->getRectangle().getSouth() == 2.0);
|
|
CHECK(maybeRegion->getRectangle().getEast() == 3.0);
|
|
CHECK(maybeRegion->getRectangle().getNorth() == 3.0);
|
|
CHECK(maybeRegion->getMinimumHeight() == 10.0);
|
|
CHECK(maybeRegion->getMaximumHeight() == 15.0);
|
|
|
|
BoundingVolume l1x0y1 = ImplicitTilingUtilities::computeBoundingVolume(
|
|
root,
|
|
OctreeTileID(1, 0, 1, 0),
|
|
Ellipsoid::WGS84);
|
|
std::optional<S2CellBoundingVolume> maybeS2 =
|
|
TileBoundingVolumes::getS2CellBoundingVolume(
|
|
l1x0y1,
|
|
Ellipsoid::WGS84);
|
|
REQUIRE(maybeS2);
|
|
CHECK(maybeS2->getCellID().getFace() == 1);
|
|
CHECK(
|
|
maybeS2->getCellID().getID() ==
|
|
S2CellID::fromQuadtreeTileID(1, QuadtreeTileID(1, 0, 1)).getID());
|
|
CHECK(maybeS2->getMinimumHeight() == 10.0);
|
|
CHECK(maybeS2->getMaximumHeight() == 15.0);
|
|
}
|
|
}
|
|
}
|