Add new (winner) neighbor index based on measurements

This commit is contained in:
tamasmeszaros 2021-06-02 15:45:11 +02:00
parent b14b000c73
commit c4507842a0
11 changed files with 327 additions and 125 deletions

View file

@ -32,7 +32,7 @@ FaceNeighborIndex its_create_neighbors_index_1(const indexed_triangle_set &its)
const int max_vertex_id_bits = std::ceil(std::log2(its.vertices.size()));
assert(max_vertex_id_bits <= 32);
std::unordered_map< EdgeID, Edge > edge_index;
std::unordered_map< EdgeID, Edge> edge_index;
// Edge id is constructed by concatenating two vertex ids, starting with
// the lowest in MSB
@ -322,6 +322,27 @@ FaceNeighborIndex its_create_neighbors_index_4(const indexed_triangle_set &its)
return index;
}
// Create an index of faces belonging to each vertex. The returned vector can
// be indexed with vertex indices and contains a list of face indices for each
// vertex.
static std::vector<std::vector<size_t>> create_vertex_faces_index(const indexed_triangle_set &its)
{
std::vector<std::vector<size_t>> index;
if (! its.vertices.empty()) {
size_t res = its.indices.size() / its.vertices.size();
index.assign(its.vertices.size(), reserve_vector<size_t>(res));
for (size_t fi = 0; fi < its.indices.size(); ++fi) {
auto &face = its.indices[fi];
index[face(0)].emplace_back(fi);
index[face(1)].emplace_back(fi);
index[face(2)].emplace_back(fi);
}
}
return index;
}
static int get_vertex_index(size_t vertex_index, const stl_triangle_vertex_indices &triangle_indices) {
if (vertex_index == triangle_indices[0]) return 0;
if (vertex_index == triangle_indices[1]) return 1;
@ -329,7 +350,7 @@ static int get_vertex_index(size_t vertex_index, const stl_triangle_vertex_indic
return -1;
}
Vec2crd get_edge_indices(int edge_index, const stl_triangle_vertex_indices &triangle_indices)
static Vec2crd get_edge_indices(int edge_index, const stl_triangle_vertex_indices &triangle_indices)
{
int next_edge_index = (edge_index == 2) ? 0 : edge_index + 1;
coord_t vi0 = triangle_indices[edge_index];
@ -577,4 +598,44 @@ FaceNeighborIndex its_create_neighbors_index_8(const indexed_triangle_set &its)
return index;
}
std::vector<Vec3crd> its_create_neighbors_index_9(const indexed_triangle_set &its)
{
const std::vector<stl_triangle_vertex_indices> &indices = its.indices;
size_t vertices_size = its.vertices.size();
if (indices.empty() || vertices_size == 0) return {};
// std::vector<std::vector<size_t>> vertex_triangles = create_vertex_faces_index(indices, vertices_size);
auto vertex_triangles = VertexFaceIndex{its};
coord_t no_value = -1;
std::vector<Vec3crd> neighbors(indices.size(), Vec3crd(no_value, no_value, no_value));
for (const stl_triangle_vertex_indices& triangle_indices : indices) {
coord_t index = &triangle_indices - &indices.front();
Vec3crd& neighbor = neighbors[index];
for (int edge_index = 0; edge_index < 3; ++edge_index) {
// check if done
coord_t& neighbor_edge = neighbor[edge_index];
if (neighbor_edge != no_value) continue;
Vec2crd edge_indices = get_edge_indices(edge_index, triangle_indices);
// IMPROVE: use same vector for 2 sides of triangle
const auto &faces_range = vertex_triangles[edge_indices[0]];
for (const size_t &face : faces_range) {
if (face <= index) continue;
const stl_triangle_vertex_indices &face_indices = indices[face];
int vertex_index = get_vertex_index(edge_indices[1], face_indices);
// NOT Contain second vertex?
if (vertex_index < 0) continue;
// Has NOT oposit direction?
if (edge_indices[0] != face_indices[(vertex_index + 1) % 3]) continue;
neighbor_edge = face;
neighbors[face][vertex_index] = index;
break;
}
// must be paired
assert(neighbor_edge != no_value);
}
}
return neighbors;
}
} // namespace Slic3r

View file

@ -11,4 +11,5 @@ std::vector<Vec3crd> its_create_neighbors_index_5(const indexed_triangle_set &it
std::vector<std::array<size_t, 3>> its_create_neighbors_index_6(const indexed_triangle_set &its);
std::vector<std::array<size_t, 3>> its_create_neighbors_index_7(const indexed_triangle_set &its);
FaceNeighborIndex its_create_neighbors_index_8(const indexed_triangle_set &its);
std::vector<Vec3crd> its_create_neighbors_index_9(const indexed_triangle_set &its);
}

View file

@ -33,9 +33,12 @@ static MeasureResult measure_index(const indexed_triangle_set &its, IndexCreator
r.t_index_create += b.getElapsedSec();
b.start();
its_split(itsn);
auto res = its_split(itsn);
b.stop();
if (res.size() != 2 || res[0].indices.size() != res[1].indices.size() )
std::cerr << "Something is wrong, split result invalid" << std::endl;
r.t_split += b.getElapsedSec();
}
@ -49,20 +52,30 @@ static indexed_triangle_set two_spheres(double detail)
{
auto sphere1 = its_make_sphere(10., 2 * PI / detail), sphere2 = sphere1;
its_transform(sphere1, Transform3f{}.translate(Vec3f{-5.f, 0.f, 0.f}));
its_transform(sphere2, Transform3f{}.translate(Vec3f{5.f, 0.f, 0.f}));
its_transform(sphere1, identity3f().translate(Vec3f{-5.f, 0.f, 0.f}));
its_transform(sphere2, identity3f().translate(Vec3f{5.f, 0.f, 0.f}));
its_merge(sphere1, sphere2);
return sphere1;
}
static const std::map<std::string, indexed_triangle_set> ToMeasure = {
{"simple", its_make_cube(10., 10., 10.) }, // this has 12 faces, 8 vertices
constexpr double sq2 = std::sqrt(2.);
static const std::pair<const std::string, indexed_triangle_set> ToMeasure[] = {
{"two_spheres_1x", two_spheres(60.)},
{"two_spheres_2x", two_spheres(120.)},
{"two_spheres_4x", two_spheres(240.)},
{"two_spheres_8x", two_spheres(480.)},
{"two_spheres_16x", two_spheres(2 * 480.)},
{"two_spheres_32x", two_spheres(2 * 2 * 480.)},
// {"two_spheres_1x", two_spheres(60.)},
// {"two_spheres_2x", two_spheres(sq2 * 60.)},
// {"two_spheres_4x", two_spheres(2 * 60.)},
// {"two_spheres_8x", two_spheres(sq2 * 2. * 60.)},
// {"two_spheres_16x", two_spheres(4. * 60.)},
// {"two_spheres_32x", two_spheres(sq2 * 4. * 60.)},
};
static const auto IndexFunctions = std::make_tuple(
@ -70,25 +83,53 @@ static const auto IndexFunctions = std::make_tuple(
std::make_pair("vojta std::sort based", [](const auto &its) { return measure_index(its, its_create_neighbors_index_2); }),
std::make_pair("vojta tbb::parallel_sort based", [](const auto &its) { return measure_index(its, its_create_neighbors_index_3); }),
std::make_pair("filip's vertex->face based", [](const auto &its) { return measure_index(its, its_create_neighbors_index_5); }),
std::make_pair("vojta's vertex->face", [](const auto &its) { return measure_index(its, its_create_neighbors_index_9); }),
std::make_pair("tamas's std::sort based", [](const auto &its) { return measure_index(its, its_create_neighbors_index_6); }),
std::make_pair("tamas's tbb::parallel_sort based", [](const auto &its) { return measure_index(its, its_create_neighbors_index_7); }),
std::make_pair("tamas's map based", [](const auto &its) { return measure_index(its, its_create_neighbors_index_8); }),
std::make_pair("tamas's map based", [](const auto &its) { return measure_index(its, its_create_neighbors_index_8); })/*,
std::make_pair("TriangleMesh split", [](const auto &its) {
TriangleMesh m{its};
MeasureResult ret;
for (int i = 0; i < 10; ++i) {
TriangleMesh m{its};
Benchmark b;
b.start();
m.repair();
m.split();
auto res = m.split();
b.stop();
if (res.size() != 2 || res[0]->size() != res[1]->size())
std::cerr << "Something is wrong, split result invalid" << std::endl;
ret.t_split += b.getElapsedSec();
}
ret.t_split /= 10;
return ret;
})
})*/
// std::make_pair("Vojta's vertex->face index", [](const auto &its){
// Benchmark b;
// b.start();
// auto index = create_vertex_faces_index(its);
// b.stop();
// if (index.size() != its.vertices.size())
// std::cerr << "Something went wrong!";
// return MeasureResult{b.getElapsedSec(), 0., 0.};
// }),
// std::make_pair("Tamas's vertex->face index", [](const auto &its){
// Benchmark b;
// b.start();
// VertexFaceIndex index{its};
// b.stop();
// if (index.size() < its.vertices.size())
// std::cerr << "Something went wrong!";
// return MeasureResult{b.getElapsedSec(), 0., 0.};
// })
);
static constexpr size_t IndexFuncNum = std::tuple_size_v<decltype (IndexFunctions)>;
@ -99,16 +140,18 @@ int main(const int argc, const char * argv[])
{
using namespace Slic3r;
std::map<std::string, std::array<MeasureResult, IndexFuncNum> > results;
std::array<MeasureResult, IndexFuncNum> results[std::size(ToMeasure)];
std::array<std::string, IndexFuncNum> funcnames;
for (auto &m : ToMeasure) {
for (size_t i = 0; i < std::size(ToMeasure); ++i) {
auto &m = ToMeasure[i];
auto &name = m.first;
auto &mesh = m.second;
libnest2d::opt::metaloop::apply([&mesh, &name, &results, &funcnames](int N, auto &e) {
std::cout << "Mesh " << name << " has " << mesh.indices.size() << " faces and " << mesh.vertices.size() << " vertices." << std::endl;
libnest2d::opt::metaloop::apply([&mesh, i, &results, &funcnames](int N, auto &e) {
MeasureResult r = e.second(mesh);
funcnames[N] = e.first;
results[name][N] = r;
results[i][N] = r;
}, IndexFunctions);
}
@ -129,10 +172,12 @@ int main(const int argc, const char * argv[])
out << std::endl;
for (auto &[name, result] : results) {
for (size_t i = 0; i < std::size(ToMeasure); ++i) {
const auto &result_row = results[i];
const std::string &name = ToMeasure[i].first;
out << name << ";";
for (auto &r : result)
out << r.full_time() << ";";
for (auto &r : result_row)
out << r.t_index_create << ";";
out << std::endl;
}