| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | // Copyright Contributors to the OpenVDB Project | ||
| 2 | // SPDX-License-Identifier: MPL-2.0 | ||
| 3 | |||
| 4 | #include <openvdb/openvdb.h> | ||
| 5 | #include <openvdb/points/PointAttribute.h> | ||
| 6 | #include <openvdb/points/PointCount.h> | ||
| 7 | #include <openvdb/points/PointConversion.h> | ||
| 8 | #include <openvdb/points/PointScatter.h> | ||
| 9 | #include <openvdb/points/PointRasterizeTrilinear.h> | ||
| 10 | |||
| 11 | #include <gtest/gtest.h> | ||
| 12 | |||
| 13 | using namespace openvdb; | ||
| 14 | |||
| 15 | 9 | class TestPointRasterize: public ::testing::Test | |
| 16 | { | ||
| 17 | public: | ||
| 18 | 9 | void SetUp() override { openvdb::initialize(); } | |
| 19 | 9 | void TearDown() override { openvdb::uninitialize(); } | |
| 20 | }; // class TestPointRasterize | ||
| 21 | |||
| 22 | struct DefaultTransfer | ||
| 23 | { | ||
| 24 | inline bool startPointLeaf(const points::PointDataTree::LeafNodeType&) { return true; } | ||
| 25 | inline bool endPointLeaf(const points::PointDataTree::LeafNodeType&) { return true; } | ||
| 26 | inline bool finalize(const Coord&, size_t) { return true; } | ||
| 27 | }; | ||
| 28 | |||
| 29 | template <typename T, bool Staggered> | ||
| 30 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
16 | inline void testTrilinear(const T& v) |
| 31 | { | ||
| 32 | static constexpr bool IsVec = ValueTraits<T>::IsVec; | ||
| 33 | using VecT = typename std::conditional<IsVec, T, math::Vec3<T>>::type; | ||
| 34 | using ResultValueT = typename std::conditional<Staggered && !IsVec, VecT, T>::type; | ||
| 35 | using ResultTreeT = typename points::PointDataTree::ValueConverter<ResultValueT>::Type; | ||
| 36 | |||
| 37 | std::vector<Vec3f> positions; | ||
| 38 |
1/4✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
16 | positions.emplace_back(Vec3f(0.0f)); |
| 39 | |||
| 40 | const double voxelSize = 0.1; | ||
| 41 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
16 | math::Transform::Ptr transform = |
| 42 | math::Transform::createLinearTransform(voxelSize); | ||
| 43 | |||
| 44 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
16 | points::PointDataGrid::Ptr points = |
| 45 | points::createPointDataGrid<points::NullCodec, | ||
| 46 | points::PointDataGrid, Vec3f>(positions, *transform); | ||
| 47 | |||
| 48 |
2/4✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
|
16 | points::appendAttribute<T>(points->tree(), "test", v); |
| 49 |
3/8✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 8 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
|
16 | TreeBase::Ptr tree = |
| 50 | points::rasterizeTrilinear<Staggered, T>(points->tree(), "test"); | ||
| 51 | |||
| 52 |
1/16✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
|
16 | EXPECT_TRUE(tree); |
| 53 | typename ResultTreeT::Ptr typed = DynamicPtrCast<ResultTreeT>(tree); | ||
| 54 |
1/16✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
|
16 | EXPECT_TRUE(typed); |
| 55 | |||
| 56 | ✗ | const ResultValueT result = typed->getValue(Coord(0,0,0)); | |
| 57 | |||
| 58 | // convert both to vecs even if they are scalars to avoid having | ||
| 59 | // to specialise this method | ||
| 60 | 16 | const VecT expected(v); | |
| 61 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
12 | const VecT vec(result); |
| 62 |
2/16✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
|
16 | EXPECT_NEAR(expected[0], vec[0], 1e-6); |
| 63 |
2/16✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
|
16 | EXPECT_NEAR(expected[1], vec[1], 1e-6); |
| 64 |
2/16✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
|
16 | EXPECT_NEAR(expected[2], vec[2], 1e-6); |
| 65 | 16 | } | |
| 66 | |||
| 67 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | TEST_F(TestPointRasterize, testTrilinearRasterizeFloat) |
| 68 | { | ||
| 69 | 1 | testTrilinear<float, false>(111.0f); | |
| 70 | 1 | testTrilinear<float, true>(111.0f); | |
| 71 | 1 | } | |
| 72 | |||
| 73 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | TEST_F(TestPointRasterize, testTrilinearRasterizeDouble) |
| 74 | { | ||
| 75 | 1 | testTrilinear<double, false>(222.0); | |
| 76 | 1 | testTrilinear<double, true>(222.0); | |
| 77 | 1 | } | |
| 78 | |||
| 79 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
2 | TEST_F(TestPointRasterize, testTrilinearRasterizeVec3f) |
| 80 | { | ||
| 81 | 1 | testTrilinear<Vec3f, false>(Vec3f(111.0f,222.0f,333.0f)); | |
| 82 | 1 | testTrilinear<Vec3f, true>(Vec3f(111.0f,222.0f,333.0f)); | |
| 83 | 1 | } | |
| 84 | |||
| 85 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
2 | TEST_F(TestPointRasterize, testTrilinearRasterizeVec3d) |
| 86 | { | ||
| 87 | 1 | testTrilinear<Vec3d, false>(Vec3d(444.0,555.0,666.0)); | |
| 88 | 1 | testTrilinear<Vec3d, true>(Vec3d(444.0,555.0,666.0)); | |
| 89 | 1 | } | |
| 90 | |||
| 91 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
2 | TEST_F(TestPointRasterize, testRasterizeWithFilter) |
| 92 | { | ||
| 93 | struct CountPointsTransferScheme | ||
| 94 | : public DefaultTransfer | ||
| 95 | , public points::VolumeTransfer<Int32Tree> | ||
| 96 | { | ||
| 97 | CountPointsTransferScheme(Int32Tree& tree) | ||
| 98 | : points::VolumeTransfer<Int32Tree>(&tree) {} | ||
| 99 | |||
| 100 | inline Int32 range(const Coord&, size_t) const { return 0; } | ||
| 101 | inline void rasterizePoint(const Coord& ijk, | ||
| 102 | const Index, | ||
| 103 | const CoordBBox&) | ||
| 104 | { | ||
| 105 | const Index offset = points::PointDataTree::LeafNodeType::coordToOffset(ijk); | ||
| 106 | auto* const data = this->template buffer<0>(); | ||
| 107 | 2 | data[offset] += 1; | |
| 108 | 2 | } | |
| 109 | }; | ||
| 110 | |||
| 111 | std::vector<Vec3f> positions; | ||
| 112 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
1 | positions.emplace_back(Vec3f(0.0f, 0.0f, 0.0f)); |
| 113 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
1 | positions.emplace_back(Vec3f(0.0f, 0.0f, 0.0f)); |
| 114 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
1 | positions.emplace_back(Vec3f(0.0f, 0.0f, 0.0f)); |
| 115 |
1/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
1 | positions.emplace_back(Vec3f(0.0f, 0.0f, 0.0f)); |
| 116 | |||
| 117 | const double voxelSize = 0.1; | ||
| 118 | math::Transform::Ptr transform = | ||
| 119 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | math::Transform::createLinearTransform(voxelSize); |
| 120 | |||
| 121 | points::PointDataGrid::Ptr points = | ||
| 122 | points::createPointDataGrid<points::NullCodec, | ||
| 123 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | points::PointDataGrid>(positions, *transform); |
| 124 | |||
| 125 | points::PointDataTree& tree = points->tree(); | ||
| 126 |
3/6✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
|
2 | points::appendGroup(tree, "test"); |
| 127 | |||
| 128 |
2/6✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
|
1 | auto groupHandle = tree.beginLeaf()->groupWriteHandle("test"); |
| 129 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | groupHandle.set(0, true); |
| 130 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | groupHandle.set(1, false); |
| 131 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | groupHandle.set(2, true); |
| 132 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | groupHandle.set(3, false); |
| 133 | |||
| 134 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | Int32Tree::Ptr intTree(new Int32Tree); |
| 135 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | intTree->setValueOn(Coord(0,0,0)); |
| 136 | |||
| 137 | CountPointsTransferScheme transfer(*intTree); | ||
| 138 |
2/6✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
|
2 | points::GroupFilter filter("test", tree.cbeginLeaf()->attributeSet()); |
| 139 | |||
| 140 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | points::rasterize(*points, transfer, filter); |
| 141 | 1 | const int count = intTree->getValue(Coord(0,0,0)); | |
| 142 |
2/18✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
|
1 | EXPECT_EQ(2, count); |
| 143 | 1 | } | |
| 144 | |||
| 145 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
2 | TEST_F(TestPointRasterize, testRasterizeWithInitializeAndFinalize) |
| 146 | { | ||
| 147 | struct LinearFunctionPointCountTransferScheme | ||
| 148 | : public DefaultTransfer | ||
| 149 | , public points::VolumeTransfer<Int32Tree> | ||
| 150 | { | ||
| 151 | LinearFunctionPointCountTransferScheme(Int32Tree& tree) : | ||
| 152 | points::VolumeTransfer<Int32Tree>(&tree) {} | ||
| 153 | |||
| 154 | inline Int32 range(const Coord&, size_t) const { return 0; } | ||
| 155 | |||
| 156 | 1 | inline void initialize(const Coord& c, size_t i, const CoordBBox& b) | |
| 157 | { | ||
| 158 | 1 | this->points::VolumeTransfer<Int32Tree>::initialize(c,i,b); | |
| 159 | auto* const data = this->template buffer<0>(); | ||
| 160 | const auto& mask = *(this->template mask<0>()); | ||
| 161 |
2/2✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
|
3 | for (auto iter = mask.beginOn(); iter; ++iter) { |
| 162 | 1 | data[iter.pos()] += 10; | |
| 163 | } | ||
| 164 | 1 | } | |
| 165 | |||
| 166 | 1 | inline bool finalize(const Coord&, size_t) | |
| 167 | { | ||
| 168 | auto* const data = this->template buffer<0>(); | ||
| 169 | const auto& mask = *(this->template mask<0>()); | ||
| 170 |
2/2✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
|
3 | for (auto iter = mask.beginOn(); iter; ++iter) { |
| 171 | 1 | data[iter.pos()] *= 2; | |
| 172 | } | ||
| 173 | 1 | return true; | |
| 174 | } | ||
| 175 | |||
| 176 | inline void rasterizePoint(const Coord& ijk, const Index, const CoordBBox&) | ||
| 177 | { | ||
| 178 | const Index offset = points::PointDataTree::LeafNodeType::coordToOffset(ijk); | ||
| 179 | auto* const data = this->template buffer<0>(); | ||
| 180 | 4 | data[offset] += 1; | |
| 181 | } | ||
| 182 | }; | ||
| 183 | |||
| 184 | std::vector<Vec3f> positions; | ||
| 185 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
1 | positions.emplace_back(Vec3f(0.0f, 0.0f, 0.0f)); |
| 186 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
1 | positions.emplace_back(Vec3f(0.0f, 0.0f, 0.0f)); |
| 187 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
1 | positions.emplace_back(Vec3f(0.0f, 0.0f, 0.0f)); |
| 188 |
1/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
1 | positions.emplace_back(Vec3f(0.0f, 0.0f, 0.0f)); |
| 189 | |||
| 190 | const double voxelSize = 0.1; | ||
| 191 | math::Transform::Ptr transform = | ||
| 192 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | math::Transform::createLinearTransform(voxelSize); |
| 193 | |||
| 194 | points::PointDataGrid::Ptr points = | ||
| 195 | points::createPointDataGrid<points::NullCodec, | ||
| 196 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | points::PointDataGrid>(positions, *transform); |
| 197 | |||
| 198 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | Int32Tree::Ptr intTree(new Int32Tree); |
| 199 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | intTree->setValueOn(Coord(0,0,0)); |
| 200 | |||
| 201 | LinearFunctionPointCountTransferScheme transfer(*intTree); | ||
| 202 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
1 | points::rasterize(*points, transfer); |
| 203 | |||
| 204 | 1 | const int value = intTree->getValue(Coord(0,0,0)); | |
| 205 |
2/18✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
|
1 | EXPECT_EQ(/*(10+4)*2*/28, value); |
| 206 | 1 | } | |
| 207 | |||
| 208 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
2 | TEST_F(TestPointRasterize, tetsSingleTreeRasterize) |
| 209 | { | ||
| 210 | struct CountPoints27TransferScheme | ||
| 211 | : public DefaultTransfer | ||
| 212 | , public points::VolumeTransfer<Int32Tree> | ||
| 213 | { | ||
| 214 | CountPoints27TransferScheme(Int32Tree& tree) | ||
| 215 | : points::VolumeTransfer<Int32Tree>(&tree) {} | ||
| 216 | |||
| 217 | /// @brief The maximum lookup range of this transfer scheme in voxels. | ||
| 218 | inline Int32 range(const Coord&, size_t) const { return 1; } | ||
| 219 | |||
| 220 | /// @brief The point stamp function. Each point which contributes to the | ||
| 221 | /// current leaf that the thread has access to will call this function | ||
| 222 | /// exactly once. | ||
| 223 | /// @param ijk The current voxel containing the point being rasterized. May | ||
| 224 | /// not be inside the destination leaf nodes. | ||
| 225 | /// @param id The point index being rasterized | ||
| 226 | /// @param bounds The active bounds of the leaf node(s) being written to. | ||
| 227 | 6 | void rasterizePoint(const Coord& ijk, const Index, const CoordBBox& bounds) | |
| 228 | { | ||
| 229 | static const Index DIM = Int32Tree::LeafNodeType::DIM; | ||
| 230 | static const Index LOG2DIM = Int32Tree::LeafNodeType::LOG2DIM; | ||
| 231 | |||
| 232 | 6 | CoordBBox intersectBox(ijk.offsetBy(-1), ijk.offsetBy(1)); | |
| 233 | 6 | intersectBox.intersect(bounds); | |
| 234 | ✗ | if (intersectBox.empty()) return; | |
| 235 | auto* const data = this->template buffer<0>(); | ||
| 236 | const auto& mask = *(this->template mask<0>()); | ||
| 237 | |||
| 238 | // loop over voxels in this leaf which are affected by this point | ||
| 239 | |||
| 240 | const Coord& a(intersectBox.min()); | ||
| 241 | const Coord& b(intersectBox.max()); | ||
| 242 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 6 times.
|
14 | for (Coord c = a; c.x() <= b.x(); ++c.x()) { |
| 243 | 8 | const Index i = ((c.x() & (DIM-1u)) << 2*LOG2DIM); | |
| 244 |
2/2✓ Branch 0 taken 12 times.
✓ Branch 1 taken 8 times.
|
20 | for (c.y() = a.y(); c.y() <= b.y(); ++c.y()) { |
| 245 | 12 | const Index j = ((c.y() & (DIM-1u)) << LOG2DIM); | |
| 246 |
2/2✓ Branch 0 taken 20 times.
✓ Branch 1 taken 12 times.
|
32 | for (c.z() = a.z(); c.z() <= b.z(); ++c.z()) { |
| 247 | ✗ | assert(bounds.isInside(c)); | |
| 248 | 20 | const Index offset = i + j + /*k*/(c.z() & (DIM-1u)); | |
| 249 |
2/2✓ Branch 1 taken 12 times.
✓ Branch 2 taken 8 times.
|
20 | if (!mask.isOn(offset)) continue; |
| 250 | 8 | data[offset] += 1; | |
| 251 | |||
| 252 | } | ||
| 253 | } | ||
| 254 | } | ||
| 255 | } | ||
| 256 | }; | ||
| 257 | |||
| 258 | std::vector<Vec3f> positions; | ||
| 259 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
1 | positions.emplace_back(Vec3f(0.0f, 0.0f, 0.0f)); |
| 260 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
1 | positions.emplace_back(Vec3f(0.1f, 0.1f, 0.1f)); |
| 261 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
1 | positions.emplace_back(Vec3f(0.2f, 0.2f, 0.2f)); |
| 262 |
1/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
1 | positions.emplace_back(Vec3f(-0.1f,-0.1f,-0.1f)); |
| 263 | |||
| 264 | const double voxelSize = 0.1; | ||
| 265 | math::Transform::Ptr transform = | ||
| 266 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | math::Transform::createLinearTransform(voxelSize); |
| 267 | |||
| 268 | points::PointDataGrid::Ptr points = | ||
| 269 | points::createPointDataGrid<points::NullCodec, | ||
| 270 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | points::PointDataGrid>(positions, *transform); |
| 271 | |||
| 272 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | Int32Tree::Ptr intTree(new Int32Tree); |
| 273 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | intTree->setValueOn(Coord(0,0,0)); |
| 274 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | intTree->setValueOn(Coord(1,1,1)); |
| 275 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | intTree->setValueOn(Coord(-1,-1,-1)); |
| 276 | |||
| 277 | CountPoints27TransferScheme transfer(*intTree); | ||
| 278 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
1 | points::rasterize(*points, transfer); |
| 279 | |||
| 280 | 1 | int count = intTree->getValue(Coord(0,0,0)); | |
| 281 |
2/16✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
|
1 | EXPECT_EQ(3, count); |
| 282 | 1 | count = intTree->getValue(Coord(1,1,1)); | |
| 283 |
2/16✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
|
1 | EXPECT_EQ(3, count); |
| 284 | 1 | count = intTree->getValue(Coord(-1,-1,-1)); | |
| 285 |
2/18✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
|
1 | EXPECT_EQ(2, count); |
| 286 | 1 | } | |
| 287 | |||
| 288 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
2 | TEST_F(TestPointRasterize, testMultiTreeRasterize) |
| 289 | { | ||
| 290 | /// @brief An example multi tree transfer scheme which rasterizes a vector | ||
| 291 | /// attribute into an int grid using length, and an int attribute | ||
| 292 | /// into a vector grid. Based on a 27 lookup stencil. | ||
| 293 | /// | ||
| 294 | struct MultiTransferScheme | ||
| 295 | : public DefaultTransfer | ||
| 296 | , public points::VolumeTransfer<Int32Tree, Vec3DTree> | ||
| 297 | { | ||
| 298 | using BaseT = points::VolumeTransfer<Int32Tree, Vec3DTree>; | ||
| 299 | |||
| 300 | MultiTransferScheme(const size_t vIdx,const size_t iIdx, | ||
| 301 | Int32Tree& t1, Vec3DTree& t2) | ||
| 302 | 1 | : BaseT(t1, t2) | |
| 303 | , mVIdx(vIdx), mIIdx(iIdx) | ||
| 304 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | , mVHandle(), mIHandle() {} |
| 305 | |||
| 306 | MultiTransferScheme(const MultiTransferScheme& other) | ||
| 307 | 2 | : BaseT(other), mVIdx(other.mVIdx), mIIdx(other.mIIdx) | |
| 308 | 1 | , mVHandle(), mIHandle() {} | |
| 309 | |||
| 310 | inline Int32 range(const Coord&, size_t) const { return 1; } | ||
| 311 | |||
| 312 | 1 | inline bool startPointLeaf(const points::PointDataTree::LeafNodeType& leaf) | |
| 313 | { | ||
| 314 | 1 | mVHandle = points::AttributeHandle<Vec3d>::create(leaf.constAttributeArray(mVIdx)); | |
| 315 | 1 | mIHandle = points::AttributeHandle<int>::create(leaf.constAttributeArray(mIIdx)); | |
| 316 | 1 | return true; | |
| 317 | } | ||
| 318 | |||
| 319 | 1 | void rasterizePoint(const Coord& ijk, const Index id, const CoordBBox& bounds) | |
| 320 | { | ||
| 321 | static const Index DIM = Int32Tree::LeafNodeType::DIM; | ||
| 322 | static const Index LOG2DIM = Int32Tree::LeafNodeType::LOG2DIM; | ||
| 323 | |||
| 324 | 1 | CoordBBox intersectBox(ijk.offsetBy(-1), ijk.offsetBy(1)); | |
| 325 | 1 | intersectBox.intersect(bounds); | |
| 326 | ✗ | if (intersectBox.empty()) return; | |
| 327 | |||
| 328 | auto* const data1 = this->template buffer<0>(); | ||
| 329 | auto* const data2 = this->template buffer<1>(); | ||
| 330 | const auto& mask = *(this->template mask<0>()); | ||
| 331 | |||
| 332 | // loop over voxels in this leaf which are affected by this point | ||
| 333 | 1 | const Vec3d& vec = mVHandle->get(id); | |
| 334 | 1 | const int integer = mIHandle->get(id); | |
| 335 | |||
| 336 | const Coord& a(intersectBox.min()); | ||
| 337 | const Coord& b(intersectBox.max()); | ||
| 338 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
|
2 | for (Coord c = a; c.x() <= b.x(); ++c.x()) { |
| 339 | 1 | const Index i = ((c.x() & (DIM-1u)) << 2*LOG2DIM); | |
| 340 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
|
2 | for (c.y() = a.y(); c.y() <= b.y(); ++c.y()) { |
| 341 | 1 | const Index j = ((c.y() & (DIM-1u)) << LOG2DIM); | |
| 342 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
|
2 | for (c.z() = a.z(); c.z() <= b.z(); ++c.z()) { |
| 343 | ✗ | assert(bounds.isInside(c)); | |
| 344 | 1 | const Index offset = i + j + /*k*/(c.z() & (DIM-1u)); | |
| 345 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
|
1 | if (!mask.isOn(offset)) continue; |
| 346 | 1 | data1[offset] += static_cast<int>(vec.length()); | |
| 347 | 1 | data2[offset] += Vec3d(integer); | |
| 348 | } | ||
| 349 | } | ||
| 350 | } | ||
| 351 | } | ||
| 352 | |||
| 353 | private: | ||
| 354 | const size_t mVIdx; | ||
| 355 | const size_t mIIdx; | ||
| 356 | points::AttributeHandle<Vec3d>::Ptr mVHandle; | ||
| 357 | points::AttributeHandle<int>::Ptr mIHandle; | ||
| 358 | }; | ||
| 359 | |||
| 360 | std::vector<Vec3f> positions; | ||
| 361 |
1/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
1 | positions.emplace_back(Vec3f(0.0f, 0.0f, 0.0f)); |
| 362 | |||
| 363 | const double voxelSize = 0.1; | ||
| 364 | math::Transform::Ptr transform = | ||
| 365 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | math::Transform::createLinearTransform(voxelSize); |
| 366 | |||
| 367 | points::PointDataGrid::Ptr points = | ||
| 368 | points::createPointDataGrid<points::NullCodec, | ||
| 369 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | points::PointDataGrid>(positions, *transform); |
| 370 | |||
| 371 | points::PointDataTree& tree = points->tree(); | ||
| 372 | |||
| 373 | const Vec3d vectorValue(444.0f,555.0f,666.0f); | ||
| 374 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
1 | points::appendAttribute<Vec3d>(tree, "testVec3d", vectorValue); |
| 375 |
2/6✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
|
1 | points::appendAttribute<int>(tree, "testInt", 7); |
| 376 | |||
| 377 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | Vec3DTree::Ptr vecTree(new Vec3DTree); |
| 378 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | Int32Tree::Ptr intTree(new Int32Tree); |
| 379 | vecTree->topologyUnion(tree); | ||
| 380 | intTree->topologyUnion(tree); | ||
| 381 | |||
| 382 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | const points::PointDataTree::LeafNodeType& leaf = *(tree.cbeginLeaf()); |
| 383 |
3/6✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
|
2 | const size_t vidx = leaf.attributeSet().descriptor().find("testVec3d"); |
| 384 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
2 | const size_t iidx = leaf.attributeSet().descriptor().find("testInt"); |
| 385 | |||
| 386 | 1 | MultiTransferScheme transfer(vidx, iidx, *intTree, *vecTree); | |
| 387 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
1 | points::rasterize(*points, transfer); |
| 388 | |||
| 389 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | const Vec3d vecResult = vecTree->getValue(Coord(0,0,0)); |
| 390 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | const int intResult = intTree->getValue(Coord(0,0,0)); |
| 391 | |||
| 392 |
2/16✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
|
1 | EXPECT_EQ(7.0, vecResult[0]); |
| 393 |
2/16✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
|
1 | EXPECT_EQ(7.0, vecResult[1]); |
| 394 |
2/16✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
|
1 | EXPECT_EQ(7.0, vecResult[2]); |
| 395 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | const int expected = static_cast<int>(vectorValue.length()); |
| 396 |
1/14✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
|
1 | EXPECT_EQ(expected, intResult); |
| 397 | 1 | } | |
| 398 | |||
| 399 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
2 | TEST_F(TestPointRasterize, testMultiTreeRasterizeWithMask) |
| 400 | { | ||
| 401 | 1 | struct CountPointsMaskTransferScheme | |
| 402 | : public DefaultTransfer | ||
| 403 | , public points::VolumeTransfer<BoolTree, Int32Tree> | ||
| 404 | { | ||
| 405 | using BaseT = points::VolumeTransfer<BoolTree, Int32Tree>; | ||
| 406 | CountPointsMaskTransferScheme(BoolTree& t1, Int32Tree& t2) | ||
| 407 | : BaseT(t1, t2) {} | ||
| 408 | |||
| 409 | inline Int32 range(const Coord&, size_t) const { return 0; } | ||
| 410 | inline void rasterizePoint(const Coord& ijk, const Index, const CoordBBox&) | ||
| 411 | { | ||
| 412 | auto* const data = this->template buffer<1>(); | ||
| 413 | const Index offset = points::PointDataTree::LeafNodeType::coordToOffset(ijk); | ||
| 414 | 1 | data[offset] += 1; | |
| 415 | } | ||
| 416 | }; | ||
| 417 | |||
| 418 | // Setup test data | ||
| 419 | std::vector<Vec3f> positions; | ||
| 420 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
1 | positions.emplace_back(Vec3f(0.0f, 0.0f, 0.0f)); |
| 421 |
1/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
1 | positions.emplace_back(Vec3f(1.0f, 1.0f, 1.0f)); |
| 422 | |||
| 423 | const double voxelSize = 0.1; | ||
| 424 | math::Transform::Ptr transform = | ||
| 425 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | math::Transform::createLinearTransform(voxelSize); |
| 426 | |||
| 427 | points::PointDataGrid::Ptr points = | ||
| 428 | points::createPointDataGrid<points::NullCodec, | ||
| 429 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | points::PointDataGrid>(positions, *transform); |
| 430 | |||
| 431 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | Int32Tree::Ptr intTree(new Int32Tree); |
| 432 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | BoolTree::Ptr topology(new BoolTree); |
| 433 | intTree->topologyUnion(points->tree()); | ||
| 434 | 1 | topology->setValueOn(Coord(0,0,0)); | |
| 435 | |||
| 436 |
1/16✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
|
1 | EXPECT_TRUE(intTree->isValueOn(Coord(10,10,10))); |
| 437 | |||
| 438 | CountPointsMaskTransferScheme transfer(*topology, *intTree); | ||
| 439 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
1 | points::rasterize(*points, transfer); |
| 440 | |||
| 441 | 1 | int count = intTree->getValue(Coord(0,0,0)); | |
| 442 |
2/16✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
|
1 | EXPECT_EQ(1, count); |
| 443 | 1 | count = intTree->getValue(Coord(10,10,10)); | |
| 444 |
2/18✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
|
1 | EXPECT_EQ(0, count); |
| 445 | 1 | } | |
| 446 | |||
| 447 | // void | ||
| 448 | // TestPointRasterize::testMultiTreeRasterizeConstTopology() | ||
| 449 | // { | ||
| 450 | // // Test const-ness is respected and works at compile time through | ||
| 451 | // // the points::rasterize function (transfer function signatures should | ||
| 452 | // // respect the const flag of the topology mask leaf nodes) | ||
| 453 | |||
| 454 | // struct CountPointsConstMaskTransferScheme | ||
| 455 | // : public DefaultTransfer, | ||
| 456 | // : public points::VolumeTransfer<const BoolTree, Int32Tree> | ||
| 457 | // { | ||
| 458 | // using VolumeTransferT = | ||
| 459 | // points::rasterize_tree_containers::MultiTreeRasterizer | ||
| 460 | // <const BoolTree, Int32Tree>; | ||
| 461 | |||
| 462 | // using BufferT = VolumeTransferT::BufferT; | ||
| 463 | // using NodeMaskT = VolumeTransferT::NodeMaskT; | ||
| 464 | |||
| 465 | // static_assert(std::is_const<NodeMaskT>::value, | ||
| 466 | // "Node mask should be const"); | ||
| 467 | // static_assert(std::is_const<VolumeTransferT::TopologyTreeT>::value, | ||
| 468 | // "TopologyTreeT should be const"); | ||
| 469 | |||
| 470 | // inline Int32 range() const { return 0; } | ||
| 471 | // inline void initialize(BufferT, NodeMaskT&, const Coord&) {} | ||
| 472 | // inline void initLeaf(const points::PointDataTree::LeafNodeType&) {} | ||
| 473 | // inline void finalize(BufferT, NodeMaskT&, const Coord&) {} | ||
| 474 | // inline void rasterizePoint(const Coord&, | ||
| 475 | // const Index, | ||
| 476 | // const CoordBBox&, | ||
| 477 | // BufferT, | ||
| 478 | // NodeMaskT&) {} | ||
| 479 | // }; | ||
| 480 | |||
| 481 | // points::PointDataTree tree; | ||
| 482 | // Int32Tree::Ptr intTree(new Int32Tree); | ||
| 483 | // BoolTree::Ptr topology(new BoolTree); | ||
| 484 | |||
| 485 | // CountPointsConstMaskTransferScheme transfer; | ||
| 486 | // CountPointsConstMaskTransferScheme::VolumeTransferT::TreeArrayT array = {intTree}; | ||
| 487 | // CountPointsConstMaskTransferScheme::VolumeTransferT container(*topology, array); | ||
| 488 | // points::rasterize(tree, transfer, container); | ||
| 489 | // } | ||
| 490 |