[core] compute the actual clipping masks that we have to draw with getStencils()
This commit is contained in:
@@ -6,6 +6,7 @@
|
||||
#include <string>
|
||||
#include <functional>
|
||||
#include <forward_list>
|
||||
#include <limits>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
@@ -48,7 +49,8 @@ public:
|
||||
|
||||
TileID parent(int8_t z, int8_t sourceMaxZoom) const;
|
||||
TileID normalized() const;
|
||||
std::forward_list<TileID> children(int8_t sourceMaxZoom) const;
|
||||
std::forward_list<TileID>
|
||||
children(int8_t sourceMaxZoom = std::numeric_limits<int8_t>::max()) const;
|
||||
bool isChildOf(const TileID&) const;
|
||||
operator std::string() const;
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <mbgl/platform/log.hpp>
|
||||
#include <mbgl/util/math.hpp>
|
||||
#include <mbgl/util/std.hpp>
|
||||
#include <mbgl/map/tile.hpp>
|
||||
|
||||
#include <list>
|
||||
@@ -10,13 +11,14 @@
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
ClipIDGenerator::Leaf::Leaf(Tile &tile_) : tile(tile_) {}
|
||||
ClipIDGenerator::Leaf::Leaf(TileID id_, ClipID& clip_) : id(id_), clip(clip_) {}
|
||||
|
||||
void ClipIDGenerator::Leaf::add(const TileID &p) {
|
||||
if (p.isChildOf(tile.id)) {
|
||||
if (p.isChildOf(id)) {
|
||||
// Ensure that no already present child is a parent of the new p.
|
||||
for (const auto& child : children) {
|
||||
if (p.isChildOf(child))
|
||||
@@ -27,27 +29,16 @@ void ClipIDGenerator::Leaf::add(const TileID &p) {
|
||||
}
|
||||
|
||||
bool ClipIDGenerator::Leaf::operator==(const Leaf &other) const {
|
||||
return tile.id == other.tile.id && children == other.children;
|
||||
}
|
||||
|
||||
bool ClipIDGenerator::reuseExisting(Leaf &leaf) {
|
||||
for (const auto& pool : pools) {
|
||||
auto existing = std::find(pool.begin(), pool.end(), leaf);
|
||||
if (existing != pool.end()) {
|
||||
leaf.tile.clip = existing->tile.clip;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return id == other.id && children == other.children;
|
||||
}
|
||||
|
||||
void ClipIDGenerator::update(std::forward_list<Tile *> tiles) {
|
||||
Pool pool;
|
||||
|
||||
tiles.sort([](const Tile *a, const Tile *b) {
|
||||
return a->id < b->id;
|
||||
});
|
||||
|
||||
std::size_t size = 0;
|
||||
|
||||
const auto end = tiles.end();
|
||||
for (auto it = tiles.begin(); it != end; it++) {
|
||||
if (!*it) {
|
||||
@@ -56,37 +47,49 @@ void ClipIDGenerator::update(std::forward_list<Tile *> tiles) {
|
||||
}
|
||||
|
||||
Tile &tile = **it;
|
||||
Leaf clip { tile };
|
||||
// Use the actual zoom level for computing the clipping mask.
|
||||
Leaf leaf{ TileID{ tile.id.sourceZ, tile.id.x, tile.id.y, tile.id.sourceZ }, tile.clip };
|
||||
|
||||
// Try to add all remaining ids as children. We sorted the tile list
|
||||
// by z earlier, so all preceding items cannot be children of the current
|
||||
// tile.
|
||||
for (auto child_it = std::next(it); child_it != end; child_it++) {
|
||||
clip.add((*child_it)->id);
|
||||
// Use the actual zoom level for computing the clipping mask.
|
||||
const auto& childID = (*child_it)->id;
|
||||
leaf.add(TileID { childID.sourceZ, childID.x, childID.y, childID.sourceZ });
|
||||
}
|
||||
clip.children.sort();
|
||||
leaf.children.sort();
|
||||
|
||||
// Loop through all existing pools and try to find a matching ClipID.
|
||||
if (!reuseExisting(clip)) {
|
||||
auto existing = std::find(pool.begin(), pool.end(), leaf);
|
||||
if (existing != pool.end()) {
|
||||
leaf.clip = existing->clip;
|
||||
} else {
|
||||
// We haven't found an existing clip ID
|
||||
pool.push_back(std::move(clip));
|
||||
leaf.clip = {};
|
||||
size++;
|
||||
}
|
||||
|
||||
pool.emplace_back(std::move(leaf));
|
||||
}
|
||||
|
||||
if (!pool.empty()) {
|
||||
const uint32_t bit_count = util::ceil_log2(pool.size() + 1);
|
||||
if (size > 0) {
|
||||
const uint32_t bit_count = util::ceil_log2(size + 1);
|
||||
const std::bitset<8> mask = uint64_t(((1ul << bit_count) - 1) << bit_offset);
|
||||
|
||||
// We are starting our count with 1 since we need at least 1 bit set to distinguish between
|
||||
// areas without any tiles whatsoever and the current area.
|
||||
uint8_t count = 1;
|
||||
for (auto& leaf : pool) {
|
||||
leaf.tile.clip.mask = mask;
|
||||
leaf.tile.clip.reference = uint32_t(count++) << bit_offset;
|
||||
for (auto& tile : tiles) {
|
||||
tile->clip.mask |= mask;
|
||||
|
||||
// Assign only to clip IDs that have no value yet.
|
||||
if (tile->clip.reference.none()) {
|
||||
tile->clip.reference = uint32_t(count++) << bit_offset;
|
||||
}
|
||||
}
|
||||
|
||||
bit_offset += bit_count;
|
||||
pools.push_front(std::move(pool));
|
||||
}
|
||||
|
||||
if (bit_offset > 8) {
|
||||
@@ -94,4 +97,58 @@ void ClipIDGenerator::update(std::forward_list<Tile *> tiles) {
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Container>
|
||||
bool coveredByChildren(const TileID& id, const Container& container) {
|
||||
for (const auto& child : id.children()) {
|
||||
const auto lower = container.lower_bound(child);
|
||||
if (lower == container.end() ||
|
||||
(lower->first != child && !coveredByChildren(child, container))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// We looked at all four immediate children and verified that they're covered.
|
||||
return true;
|
||||
}
|
||||
|
||||
std::map<TileID, ClipID> ClipIDGenerator::getStencils() const {
|
||||
std::map<TileID, ClipID> stencils;
|
||||
|
||||
// Merge everything.
|
||||
for (auto& leaf : pool) {
|
||||
auto res = stencils.emplace(leaf.id, leaf.clip);
|
||||
if (!res.second) {
|
||||
// Merge with the existing ClipID when there was already an element with the
|
||||
// same tile ID.
|
||||
res.first->second |= leaf.clip;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto it = stencils.begin(); it != stencils.end(); ++it) {
|
||||
auto& childId = it->first;
|
||||
auto& childClip = it->second;
|
||||
|
||||
// Loop through all preceding stencils, and find all parents.
|
||||
|
||||
for (auto parentIt = std::reverse_iterator<std::map<TileID, ClipID>::iterator>(it);
|
||||
parentIt != stencils.rend(); ++parentIt) {
|
||||
auto& parentId = parentIt->first;
|
||||
if (childId.isChildOf(parentId)) {
|
||||
// Once we have a parent, we add the bits that this ID hasn't set yet.
|
||||
const auto& parentClip = parentIt->second;
|
||||
const auto mask = ~(childClip.mask & parentClip.mask);
|
||||
childClip.reference |= mask & parentClip.reference;
|
||||
childClip.mask |= parentClip.mask;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Remove tiles that are entirely covered by children.
|
||||
util::erase_if(stencils, [&] (const auto& stencil) {
|
||||
return coveredByChildren(stencil.first, stencils);
|
||||
});
|
||||
|
||||
return stencils;
|
||||
}
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
namespace mbgl {
|
||||
|
||||
class Tile;
|
||||
class TileID;
|
||||
|
||||
struct ClipID {
|
||||
inline ClipID() {}
|
||||
@@ -26,28 +25,33 @@ struct ClipID {
|
||||
inline bool operator==(const ClipID &other) const {
|
||||
return mask == other.mask && reference == other.reference;
|
||||
}
|
||||
|
||||
inline ClipID& operator|=(const ClipID &other) {
|
||||
mask |= other.mask;
|
||||
reference |= other.reference;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
class ClipIDGenerator {
|
||||
private:
|
||||
struct Leaf {
|
||||
Leaf(Tile &tile);
|
||||
Leaf(TileID, ClipID&);
|
||||
void add(const TileID &p);
|
||||
bool operator==(const Leaf &other) const;
|
||||
|
||||
Tile &tile;
|
||||
const TileID id;
|
||||
std::forward_list<TileID> children;
|
||||
ClipID& clip;
|
||||
};
|
||||
|
||||
typedef std::vector<Leaf> Pool;
|
||||
std::forward_list<Pool> pools;
|
||||
uint8_t bit_offset = 0;
|
||||
|
||||
private:
|
||||
bool reuseExisting(Leaf &leaf);
|
||||
std::vector<Leaf> pool;
|
||||
|
||||
public:
|
||||
void update(std::forward_list<Tile *> tiles);
|
||||
|
||||
std::map<TileID, ClipID> getStencils() const;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -8,9 +8,9 @@
|
||||
|
||||
using namespace mbgl;
|
||||
|
||||
template <typename T> void generate(const T &sources) {
|
||||
ClipIDGenerator generator;
|
||||
using Stencil = std::pair<const TileID, ClipID>;
|
||||
|
||||
template <typename T> void generate(ClipIDGenerator& generator, const T &sources) {
|
||||
for (size_t j = 0; j < sources.size(); j++) {
|
||||
std::forward_list<Tile *> tile_ptrs;
|
||||
std::transform(sources[j].begin(), sources[j].end(), std::front_inserter(tile_ptrs), [](const std::shared_ptr<Tile> &tile) { return tile.get(); });
|
||||
@@ -18,7 +18,7 @@ template <typename T> void generate(const T &sources) {
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T> void print(const T &sources) {
|
||||
void print(const std::vector<std::vector<std::shared_ptr<Tile>>> &sources) {
|
||||
for (size_t j = 0; j < sources.size(); j++) {
|
||||
for (size_t i = 0; i < sources[j].size(); i++) {
|
||||
std::cout << " ASSERT_EQ(ClipID(\"" << sources[j][i]->clip.mask << "\", \"" << sources[j][i]->clip.reference << "\"), sources[" << j << "][" << i << "]->clip);\n";
|
||||
@@ -26,6 +26,18 @@ template <typename T> void print(const T &sources) {
|
||||
}
|
||||
}
|
||||
|
||||
void print(const std::map<TileID, ClipID>& stencils) {
|
||||
std::cout << " auto it = stencils.begin();\n";
|
||||
std::cout << " ASSERT_EQ(" << stencils.size() << ", stencils.size());\n";
|
||||
for (auto& stencil : stencils) {
|
||||
std::cout << " ASSERT_EQ(Stencil(TileID{ " << (int)stencil.first.z << ", "
|
||||
<< stencil.first.x << ", " << stencil.first.y << ", "
|
||||
<< (int)stencil.first.sourceZ << " }, { \"" << stencil.second.mask.to_string()
|
||||
<< "\", \"" << stencil.second.reference.to_string() << "\"}), *it++);\n";
|
||||
}
|
||||
std::cout << " ASSERT_EQ(stencils.end(), it);\n";
|
||||
}
|
||||
|
||||
TEST(ClipIDs, ParentAndFourChildren) {
|
||||
const std::vector<std::vector<std::shared_ptr<Tile>>> sources = {
|
||||
{
|
||||
@@ -37,7 +49,8 @@ TEST(ClipIDs, ParentAndFourChildren) {
|
||||
},
|
||||
};
|
||||
|
||||
generate(sources);
|
||||
ClipIDGenerator generator;
|
||||
generate(generator, sources);
|
||||
// print(sources);
|
||||
|
||||
ASSERT_EQ(ClipID("00000111", "00000010"), sources[0][0]->clip);
|
||||
@@ -45,6 +58,18 @@ TEST(ClipIDs, ParentAndFourChildren) {
|
||||
ASSERT_EQ(ClipID("00000111", "00000100"), sources[0][2]->clip);
|
||||
ASSERT_EQ(ClipID("00000111", "00000101"), sources[0][3]->clip);
|
||||
ASSERT_EQ(ClipID("00000111", "00000001"), sources[0][4]->clip);
|
||||
|
||||
const auto stencils = generator.getStencils();
|
||||
// print(stencils);
|
||||
|
||||
auto it = stencils.begin();
|
||||
ASSERT_EQ(4, stencils.size());
|
||||
ASSERT_EQ(Stencil(TileID{ 1, 0, 0, 1 }, { "00000111", "00000010"}), *it++);
|
||||
ASSERT_EQ(Stencil(TileID{ 1, 0, 1, 1 }, { "00000111", "00000011"}), *it++);
|
||||
ASSERT_EQ(Stencil(TileID{ 1, 1, 0, 1 }, { "00000111", "00000100"}), *it++);
|
||||
ASSERT_EQ(Stencil(TileID{ 1, 1, 1, 1 }, { "00000111", "00000101"}), *it++);
|
||||
ASSERT_EQ(stencils.end(), it);
|
||||
|
||||
}
|
||||
|
||||
TEST(ClipIDs, ParentAndFourChildrenNegative) {
|
||||
@@ -58,7 +83,8 @@ TEST(ClipIDs, ParentAndFourChildrenNegative) {
|
||||
},
|
||||
};
|
||||
|
||||
generate(sources);
|
||||
ClipIDGenerator generator;
|
||||
generate(generator, sources);
|
||||
// print(sources);
|
||||
|
||||
ASSERT_EQ(ClipID("00000111", "00000010"), sources[0][0]->clip);
|
||||
@@ -66,6 +92,17 @@ TEST(ClipIDs, ParentAndFourChildrenNegative) {
|
||||
ASSERT_EQ(ClipID("00000111", "00000100"), sources[0][2]->clip);
|
||||
ASSERT_EQ(ClipID("00000111", "00000101"), sources[0][3]->clip);
|
||||
ASSERT_EQ(ClipID("00000111", "00000001"), sources[0][4]->clip);
|
||||
|
||||
const auto stencils = generator.getStencils();
|
||||
// print(stencils);
|
||||
|
||||
auto it = stencils.begin();
|
||||
ASSERT_EQ(4, stencils.size());
|
||||
ASSERT_EQ(Stencil(TileID{ 1, -2, 0, 1 }, { "00000111", "00000010"}), *it++);
|
||||
ASSERT_EQ(Stencil(TileID{ 1, -2, 1, 1 }, { "00000111", "00000011"}), *it++);
|
||||
ASSERT_EQ(Stencil(TileID{ 1, -1, 0, 1 }, { "00000111", "00000100"}), *it++);
|
||||
ASSERT_EQ(Stencil(TileID{ 1, -1, 1, 1 }, { "00000111", "00000101"}), *it++);
|
||||
ASSERT_EQ(stencils.end(), it);
|
||||
}
|
||||
|
||||
TEST(ClipIDs, NegativeParentAndMissingLevel) {
|
||||
@@ -79,7 +116,8 @@ TEST(ClipIDs, NegativeParentAndMissingLevel) {
|
||||
},
|
||||
};
|
||||
|
||||
generate(sources);
|
||||
ClipIDGenerator generator;
|
||||
generate(generator, sources);
|
||||
// print(sources);
|
||||
|
||||
ASSERT_EQ(ClipID("00000111", "00000001"), sources[0][0]->clip);
|
||||
@@ -87,6 +125,17 @@ TEST(ClipIDs, NegativeParentAndMissingLevel) {
|
||||
ASSERT_EQ(ClipID("00000111", "00000011"), sources[0][2]->clip);
|
||||
ASSERT_EQ(ClipID("00000111", "00000101"), sources[0][3]->clip);
|
||||
ASSERT_EQ(ClipID("00000111", "00000010"), sources[0][4]->clip);
|
||||
|
||||
const auto stencils = generator.getStencils();
|
||||
// print(stencils);
|
||||
|
||||
auto it = stencils.begin();
|
||||
ASSERT_EQ(4, stencils.size());
|
||||
ASSERT_EQ(Stencil(TileID{ 2, -2, 0, 2 }, { "00000111", "00000010"}), *it++);
|
||||
ASSERT_EQ(Stencil(TileID{ 2, -2, 1, 2 }, { "00000111", "00000011"}), *it++);
|
||||
ASSERT_EQ(Stencil(TileID{ 2, -1, 0, 2 }, { "00000111", "00000100"}), *it++);
|
||||
ASSERT_EQ(Stencil(TileID{ 2, -1, 1, 2 }, { "00000111", "00000101"}), *it++);
|
||||
ASSERT_EQ(stencils.end(), it);
|
||||
}
|
||||
|
||||
|
||||
@@ -103,7 +152,8 @@ TEST(ClipIDs, SevenOnSameLevel) {
|
||||
},
|
||||
};
|
||||
|
||||
generate(sources);
|
||||
ClipIDGenerator generator;
|
||||
generate(generator, sources);
|
||||
// print(sources);
|
||||
|
||||
ASSERT_EQ(ClipID("00000111", "00000001"), sources[0][0]->clip);
|
||||
@@ -113,6 +163,20 @@ TEST(ClipIDs, SevenOnSameLevel) {
|
||||
ASSERT_EQ(ClipID("00000111", "00000101"), sources[0][4]->clip);
|
||||
ASSERT_EQ(ClipID("00000111", "00000110"), sources[0][5]->clip);
|
||||
ASSERT_EQ(ClipID("00000111", "00000111"), sources[0][6]->clip);
|
||||
|
||||
const auto stencils = generator.getStencils();
|
||||
// print(stencils);
|
||||
|
||||
auto it = stencils.begin();
|
||||
ASSERT_EQ(7, stencils.size());
|
||||
ASSERT_EQ(Stencil(TileID{ 2, 0, 0, 2 }, { "00000111", "00000001"}), *it++);
|
||||
ASSERT_EQ(Stencil(TileID{ 2, 0, 1, 2 }, { "00000111", "00000010"}), *it++);
|
||||
ASSERT_EQ(Stencil(TileID{ 2, 0, 2, 2 }, { "00000111", "00000011"}), *it++);
|
||||
ASSERT_EQ(Stencil(TileID{ 2, 1, 0, 2 }, { "00000111", "00000100"}), *it++);
|
||||
ASSERT_EQ(Stencil(TileID{ 2, 1, 1, 2 }, { "00000111", "00000101"}), *it++);
|
||||
ASSERT_EQ(Stencil(TileID{ 2, 1, 2, 2 }, { "00000111", "00000110"}), *it++);
|
||||
ASSERT_EQ(Stencil(TileID{ 2, 2, 0, 2 }, { "00000111", "00000111"}), *it++);
|
||||
ASSERT_EQ(stencils.end(), it);
|
||||
}
|
||||
|
||||
TEST(ClipIDs, MultipleLevels) {
|
||||
@@ -133,7 +197,8 @@ TEST(ClipIDs, MultipleLevels) {
|
||||
},
|
||||
};
|
||||
|
||||
generate(sources);
|
||||
ClipIDGenerator generator;
|
||||
generate(generator, sources);
|
||||
// print(sources);
|
||||
|
||||
ASSERT_EQ(ClipID("00001111", "00000001"), sources[0][0]->clip);
|
||||
@@ -148,6 +213,23 @@ TEST(ClipIDs, MultipleLevels) {
|
||||
ASSERT_EQ(ClipID("00001111", "00000010"), sources[0][9]->clip);
|
||||
ASSERT_EQ(ClipID("00001111", "00000111"), sources[0][10]->clip);
|
||||
ASSERT_EQ(ClipID("00001111", "00001000"), sources[0][11]->clip);
|
||||
|
||||
const auto stencils = generator.getStencils();
|
||||
// print(stencils);
|
||||
|
||||
auto it = stencils.begin();
|
||||
ASSERT_EQ(10, stencils.size());
|
||||
ASSERT_EQ(Stencil(TileID{ 2, 1, 0, 2 }, { "00001111", "00000010"}), *it++);
|
||||
ASSERT_EQ(Stencil(TileID{ 3, 0, 0, 3 }, { "00001111", "00000011"}), *it++);
|
||||
ASSERT_EQ(Stencil(TileID{ 3, 1, 0, 3 }, { "00001111", "00000101"}), *it++);
|
||||
ASSERT_EQ(Stencil(TileID{ 3, 1, 1, 3 }, { "00001111", "00000110"}), *it++);
|
||||
ASSERT_EQ(Stencil(TileID{ 3, 2, 0, 3 }, { "00001111", "00000111"}), *it++);
|
||||
ASSERT_EQ(Stencil(TileID{ 3, 2, 1, 3 }, { "00001111", "00001000"}), *it++);
|
||||
ASSERT_EQ(Stencil(TileID{ 4, 0, 2, 4 }, { "00001111", "00001001"}), *it++);
|
||||
ASSERT_EQ(Stencil(TileID{ 4, 0, 3, 4 }, { "00001111", "00001010"}), *it++);
|
||||
ASSERT_EQ(Stencil(TileID{ 4, 1, 2, 4 }, { "00001111", "00001011"}), *it++);
|
||||
ASSERT_EQ(Stencil(TileID{ 4, 1, 3, 4 }, { "00001111", "00001100"}), *it++);
|
||||
ASSERT_EQ(stencils.end(), it);
|
||||
}
|
||||
|
||||
|
||||
@@ -157,18 +239,19 @@ TEST(ClipIDs, Bug206) {
|
||||
std::make_shared<Tile>(TileID { 10, 162, 395, 10 }),
|
||||
std::make_shared<Tile>(TileID { 10, 162, 396, 10 }),
|
||||
std::make_shared<Tile>(TileID { 10, 163, 395, 10 }),
|
||||
std::make_shared<Tile>(TileID { 11, 326, 791, 10 }),
|
||||
std::make_shared<Tile>(TileID { 12, 654, 1582, 10 }),
|
||||
std::make_shared<Tile>(TileID { 12, 654, 1583, 10 }),
|
||||
std::make_shared<Tile>(TileID { 12, 655, 1582, 10 }),
|
||||
std::make_shared<Tile>(TileID { 12, 655, 1583, 10 }),
|
||||
std::make_shared<Tile>(TileID { 11, 326, 791, 11 }),
|
||||
std::make_shared<Tile>(TileID { 12, 654, 1582, 12 }),
|
||||
std::make_shared<Tile>(TileID { 12, 654, 1583, 12 }),
|
||||
std::make_shared<Tile>(TileID { 12, 655, 1582, 12 }),
|
||||
std::make_shared<Tile>(TileID { 12, 655, 1583, 12 }),
|
||||
std::make_shared<Tile>(TileID { 10, 163, 396, 10 }),
|
||||
std::make_shared<Tile>(TileID { 10, 164, 395, 10 }),
|
||||
std::make_shared<Tile>(TileID { 10, 164, 396, 10 }),
|
||||
},
|
||||
};
|
||||
|
||||
generate(sources);
|
||||
ClipIDGenerator generator;
|
||||
generate(generator, sources);
|
||||
// print(sources);
|
||||
|
||||
ASSERT_EQ(ClipID("00001111", "00000001"), sources[0][0]->clip);
|
||||
@@ -182,6 +265,24 @@ TEST(ClipIDs, Bug206) {
|
||||
ASSERT_EQ(ClipID("00001111", "00000100"), sources[0][8]->clip);
|
||||
ASSERT_EQ(ClipID("00001111", "00000101"), sources[0][9]->clip);
|
||||
ASSERT_EQ(ClipID("00001111", "00000110"), sources[0][10]->clip);
|
||||
|
||||
const auto stencils = generator.getStencils();
|
||||
// print(stencils);
|
||||
|
||||
auto it = stencils.begin();
|
||||
ASSERT_EQ(11, stencils.size());
|
||||
ASSERT_EQ(Stencil(TileID{ 10, 162, 395, 10 }, { "00001111", "00000001"}), *it++);
|
||||
ASSERT_EQ(Stencil(TileID{ 10, 162, 396, 10 }, { "00001111", "00000010"}), *it++);
|
||||
ASSERT_EQ(Stencil(TileID{ 10, 163, 395, 10 }, { "00001111", "00000011"}), *it++);
|
||||
ASSERT_EQ(Stencil(TileID{ 10, 163, 396, 10 }, { "00001111", "00000100"}), *it++);
|
||||
ASSERT_EQ(Stencil(TileID{ 10, 164, 395, 10 }, { "00001111", "00000101"}), *it++);
|
||||
ASSERT_EQ(Stencil(TileID{ 10, 164, 396, 10 }, { "00001111", "00000110"}), *it++);
|
||||
ASSERT_EQ(Stencil(TileID{ 11, 326, 791, 11 }, { "00001111", "00000111"}), *it++);
|
||||
ASSERT_EQ(Stencil(TileID{ 12, 654, 1582, 12 }, { "00001111", "00001000"}), *it++);
|
||||
ASSERT_EQ(Stencil(TileID{ 12, 654, 1583, 12 }, { "00001111", "00001001"}), *it++);
|
||||
ASSERT_EQ(Stencil(TileID{ 12, 655, 1582, 12 }, { "00001111", "00001010"}), *it++);
|
||||
ASSERT_EQ(Stencil(TileID{ 12, 655, 1583, 12 }, { "00001111", "00001011"}), *it++);
|
||||
ASSERT_EQ(stencils.end(), it);
|
||||
}
|
||||
|
||||
|
||||
@@ -208,27 +309,44 @@ TEST(ClipIDs, MultipleSources) {
|
||||
},
|
||||
};
|
||||
|
||||
generate(sources);
|
||||
ClipIDGenerator generator;
|
||||
generate(generator, sources);
|
||||
// print(sources);
|
||||
|
||||
ASSERT_EQ(ClipID("00000111", "00000001"), sources[0][0]->clip);
|
||||
ASSERT_EQ(ClipID("00000111", "00000010"), sources[0][1]->clip);
|
||||
ASSERT_EQ(ClipID("00000111", "00000011"), sources[0][2]->clip);
|
||||
ASSERT_EQ(ClipID("00000111", "00000100"), sources[0][3]->clip);
|
||||
|
||||
ASSERT_EQ(ClipID("00011000", "00001000"), sources[1][0]->clip);
|
||||
ASSERT_EQ(ClipID("00000111", "00000010"), sources[1][1]->clip);
|
||||
ASSERT_EQ(ClipID("00011111", "00000010"), sources[1][1]->clip);
|
||||
ASSERT_EQ(ClipID("00011000", "00010000"), sources[1][2]->clip);
|
||||
ASSERT_EQ(ClipID("00000111", "00000100"), sources[1][3]->clip);
|
||||
ASSERT_EQ(ClipID("00011111", "00000100"), sources[1][3]->clip);
|
||||
|
||||
ASSERT_EQ(ClipID("11100000", "00100000"), sources[2][0]->clip);
|
||||
ASSERT_EQ(ClipID("11100000", "01000000"), sources[2][1]->clip);
|
||||
ASSERT_EQ(ClipID("11100000", "01100000"), sources[2][2]->clip);
|
||||
ASSERT_EQ(ClipID("11100000", "10000000"), sources[2][3]->clip);
|
||||
ASSERT_EQ(ClipID("00011000", "00010000"), sources[2][4]->clip);
|
||||
ASSERT_EQ(ClipID("11111000", "00010000"), sources[2][4]->clip);
|
||||
|
||||
const auto stencils = generator.getStencils();
|
||||
// print(stencils);
|
||||
|
||||
auto it = stencils.begin();
|
||||
ASSERT_EQ(7, stencils.size());
|
||||
ASSERT_EQ(Stencil(TileID{ 1, 0, 0, 1 }, { "11111111", "00101001"}), *it++);
|
||||
ASSERT_EQ(Stencil(TileID{ 1, 0, 1, 1 }, { "11111111", "01001001"}), *it++);
|
||||
ASSERT_EQ(Stencil(TileID{ 1, 1, 0, 1 }, { "11111111", "01101001"}), *it++);
|
||||
ASSERT_EQ(Stencil(TileID{ 1, 1, 1, 1 }, { "11111111", "10000010"}), *it++);
|
||||
ASSERT_EQ(Stencil(TileID{ 2, 1, 1, 2 }, { "11111111", "00010001"}), *it++);
|
||||
ASSERT_EQ(Stencil(TileID{ 2, 2, 1, 2 }, { "11111111", "01101011"}), *it++);
|
||||
ASSERT_EQ(Stencil(TileID{ 2, 2, 2, 2 }, { "11111111", "10000100"}), *it++);
|
||||
ASSERT_EQ(stencils.end(), it);
|
||||
}
|
||||
|
||||
|
||||
TEST(ClipIDs, DuplicateIDs) {
|
||||
const std::vector<std::vector<std::shared_ptr<Tile>>> sources = {
|
||||
const std::vector<std::vector<std::shared_ptr<Tile>>> sources = {
|
||||
{
|
||||
std::make_shared<Tile>(TileID { 2, 0, 0, 2 }),
|
||||
std::make_shared<Tile>(TileID { 2, 0, 1, 2 }),
|
||||
@@ -240,7 +358,8 @@ TEST(ClipIDs, DuplicateIDs) {
|
||||
}
|
||||
};
|
||||
|
||||
generate(sources);
|
||||
ClipIDGenerator generator;
|
||||
generate(generator, sources);
|
||||
// print(sources);
|
||||
|
||||
ASSERT_EQ(ClipID("00000011", "00000001"), sources[0][0]->clip);
|
||||
@@ -248,4 +367,45 @@ TEST(ClipIDs, DuplicateIDs) {
|
||||
ASSERT_EQ(ClipID("00000011", "00000001"), sources[1][0]->clip);
|
||||
ASSERT_EQ(ClipID("00000011", "00000010"), sources[1][1]->clip);
|
||||
ASSERT_EQ(ClipID("00000011", "00000010"), sources[1][2]->clip);
|
||||
|
||||
const auto stencils = generator.getStencils();
|
||||
// print(stencils);
|
||||
|
||||
auto it = stencils.begin();
|
||||
ASSERT_EQ(2, stencils.size());
|
||||
ASSERT_EQ(Stencil(TileID{ 2, 0, 0, 2 }, { "00000011", "00000001"}), *it++);
|
||||
ASSERT_EQ(Stencil(TileID{ 2, 0, 1, 2 }, { "00000011", "00000010"}), *it++);
|
||||
ASSERT_EQ(stencils.end(), it);
|
||||
}
|
||||
|
||||
TEST(ClipIDs, SecondSourceHasParentOfFirstSource) {
|
||||
const std::vector<std::vector<std::shared_ptr<Tile>>> sources = {
|
||||
{
|
||||
std::make_shared<Tile>(TileID { 1, 0, 0, 1 }),
|
||||
},
|
||||
{
|
||||
std::make_shared<Tile>(TileID { 0, 0, 0, 0 }),
|
||||
std::make_shared<Tile>(TileID { 1, 0, 0, 1 }),
|
||||
},
|
||||
{
|
||||
std::make_shared<Tile>(TileID { 0, 0, 0, 0 }),
|
||||
}
|
||||
};
|
||||
|
||||
ClipIDGenerator generator;
|
||||
generate(generator, sources);
|
||||
// print(sources);
|
||||
|
||||
ASSERT_EQ(ClipID("00000001", "00000001"), sources[0][0]->clip);
|
||||
ASSERT_EQ(ClipID("00000010", "00000010"), sources[1][0]->clip);
|
||||
ASSERT_EQ(ClipID("00000011", "00000001"), sources[1][1]->clip);
|
||||
|
||||
const auto stencils = generator.getStencils();
|
||||
// print(stencils);
|
||||
|
||||
auto it = stencils.begin();
|
||||
ASSERT_EQ(2, stencils.size());
|
||||
ASSERT_EQ(Stencil(TileID{ 0, 0, 0, 0 }, { "00000110", "00000110"}), *it++);
|
||||
ASSERT_EQ(Stencil(TileID{ 1, 0, 0, 1 }, { "00000111", "00000101"}), *it++);
|
||||
ASSERT_EQ(stencils.end(), it);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user