Last active
July 2, 2022 07:11
-
-
Save tomilov/28d64a64e215cd756ab0ce87624f7e6c to your computer and use it in GitHub Desktop.
make AA box consisting of inherently sorted triangles from two points
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iterator> | |
#include <algorithm> | |
#include <tuple> | |
#include <vector> | |
#include <iostream> | |
#include <numeric> | |
#include <functional> | |
#include <random> | |
#include <cassert> | |
#include <cstdlib> | |
namespace | |
{ | |
using F = float; | |
struct Vertex | |
{ | |
F x, y, z; | |
bool operator<(const Vertex & rhs) const | |
{ | |
return std::tie(x, y, z) < std::tie(rhs.x, rhs.y, rhs.z); | |
} | |
}; | |
struct Triangle | |
{ | |
Vertex a, b, c; | |
bool operator<(const Triangle & rhs) const | |
{ | |
return std::tie(a, b, c) < std::tie(rhs.a, rhs.b, rhs.c); | |
} | |
}; | |
template<typename TriangleOutputIterator> | |
TriangleOutputIterator putBox(TriangleOutputIterator out, const Vertex & a, const Vertex & b) | |
{ | |
assert(a.x < b.x); | |
assert(a.y < b.y); | |
assert(a.z < b.z); | |
Vertex v[] = {a, a, a, b, b, b}; | |
v[0].z = b.z; | |
v[1].y = b.y; | |
v[2].x = b.x; | |
v[3].x = a.x; | |
v[4].y = a.y; | |
v[5].z = a.z; | |
*out++ = {a, v[0], v[3]}; | |
*out++ = {a, v[0], v[4]}; | |
*out++ = {a, v[1], v[3]}; | |
*out++ = {a, v[1], v[5]}; | |
*out++ = {a, v[2], v[4]}; | |
*out++ = {a, v[2], v[5]}; | |
*out++ = {v[0], v[3], b}; | |
*out++ = {v[0], v[4], b}; | |
*out++ = {v[1], v[3], b}; | |
*out++ = {v[1], v[5], b}; | |
*out++ = {v[2], v[4], b}; | |
*out++ = {v[2], v[5], b}; | |
return out; | |
} | |
constexpr int kIntBboxSize = 10; | |
constexpr int kFloatDigits = std::numeric_limits<F>::digits; | |
using RandomValueType = typename std::mt19937::result_type; | |
using UniformIntDistribution = std::uniform_int_distribution<>; | |
using UniformIntParam = typename UniformIntDistribution::param_type; | |
std::mt19937 gen; | |
UniformIntDistribution uniformInt; | |
F genFloat() | |
{ | |
return std::generate_canonical<F, kFloatDigits>(gen); | |
} | |
void genComponent(F & f, int min = -kIntBboxSize, int max = +kIntBboxSize) | |
{ | |
assert(!(max < min)); | |
f = F(uniformInt(gen, UniformIntParam(min, max))); | |
if ((false)) { | |
const int pow = uniformInt(gen, UniformIntParam(1, kFloatDigits)); | |
auto fuzz = genFloat(); | |
fuzz += fuzz; | |
fuzz -= F(1); // lost 1 bit of mantissa's randomness | |
f += std::scalbn(fuzz, -pow); | |
if (f < F(min)) { | |
f += F(max - min); | |
} else if (F(max) < f) { | |
f += F(min - max); | |
} | |
} | |
} | |
} // namespace | |
int main() | |
{ | |
for (int i = 0; i < 100000; ++i) { | |
std::vector<Triangle> box; | |
Vertex u; | |
genComponent(u.x, -kIntBboxSize, kIntBboxSize - 1); | |
genComponent(u.y, -kIntBboxSize, kIntBboxSize - 1); | |
genComponent(u.z, -kIntBboxSize, kIntBboxSize - 1); | |
Vertex v; | |
genComponent(v.x, u.x + 1, kIntBboxSize); | |
genComponent(v.y, u.y + 1, kIntBboxSize); | |
genComponent(v.z, u.z + 1, kIntBboxSize); | |
putBox(std::back_inserter(box), u, v); | |
for (const auto & [a, b, c] : box) { | |
assert(!(b < a) && !(c < b)); | |
} | |
{ | |
auto vertices = {&box[0].a, &box[0].b, &box[2].b, &box[2].c, &box[4].b, &box[4].c, &box[5].c, &box[6].c}; | |
[[maybe_unused]] const auto vertexLess = [](auto l, auto r) { return *l < *r; }; | |
assert(std::is_sorted(std::cbegin(vertices), std::cend(vertices))); | |
assert(std::adjacent_find(std::cbegin(vertices), std::cend(vertices), std::not_fn(vertexLess)) == std::cend(vertices)); | |
} | |
if (!std::is_sorted(std::cbegin(box), std::cend(box)) || (std::adjacent_find(std::cbegin(box), std::cend(box), std::not_fn(std::less<Triangle>{})) != std::cend(box))) { | |
for (const auto & [a, b, c] : box) { | |
std::cout << a.x << ' ' << a.y << ' ' << a.z << std::endl; | |
std::cout << b.x << ' ' << b.y << ' ' << b.z << std::endl; | |
std::cout << c.x << ' ' << c.y << ' ' << c.z << std::endl; | |
std::cout << std::endl; | |
} | |
std::vector<std::size_t> order(box.size()); | |
std::iota(std::begin(order), std::end(order), 0); | |
const auto less = [&](std::size_t l, std::size_t r) -> bool | |
{ | |
return box[l] < box[r]; | |
}; | |
std::sort(std::begin(order), std::end(order), less); | |
std::copy(std::cbegin(order), std::cend(order), std::ostream_iterator<std::size_t>(std::cout, ", ")); | |
std::cout << std::endl; | |
return EXIT_FAILURE; | |
} | |
} | |
return EXIT_SUCCESS; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment