OrcaSlicer latest
OrcaSlicer
Loading...
Searching...
No Matches
QuadricEdgeCollapse Namespace Reference

Classes

class  SymMat
struct  Error
struct  TriangleInfo
struct  VertexInfo
struct  EdgeInfo
struct  CopyEdgeInfo

Typedefs

using Vertices = std::vector<stl_vertex>
using Triangle = stl_triangle_vertex_indices
using Indices = std::vector<stl_triangle_vertex_indices>
using ThrowOnCancel = std::function<void(void)>
using StatusFn = std::function<void(int)>
using Errors = std::vector<Error>
using TriangleInfos = std::vector<TriangleInfo>
using VertexInfos = std::vector<VertexInfo>
using EdgeInfos = std::vector<EdgeInfo>
using CopyEdgeInfos = std::vector<CopyEdgeInfo>

Functions

Vec3d create_normal (const Triangle &triangle, const Vertices &vertices)
std::array< Vec3d, 3 > create_vertices (uint32_t id_v1, uint32_t id_v2, const Vertices &vertices)
std::array< double, 3 > vertices_error (const SymMat &q, const std::array< Vec3d, 3 > &vertices)
double calculate_determinant (const SymMat &q)
double calculate_error (uint32_t id_v1, uint32_t id_v2, const SymMat &q, const Vertices &vertices)
Vec3f calculate_vertex (uint32_t id_v1, uint32_t id_v2, const SymMat &q, const Vertices &vertices)
Vec3d calculate_vertex (double det, const SymMat &q)
double vertex_error (const SymMat &q, const Vec3d &vertex)
SymMat create_quadric (const Triangle &t, const Vec3d &n, const Vertices &vertices)
std::tuple< TriangleInfos, VertexInfos, EdgeInfos, Errors > init (const indexed_triangle_set &its, ThrowOnCancel &throw_on_cancel, StatusFn &status_fn)
std::optional< uint32_t > find_triangle_index1 (uint32_t vi, const VertexInfo &v_info, uint32_t ti, const EdgeInfos &e_infos, const Indices &indices)
void reorder_edges (EdgeInfos &e_infos, const VertexInfo &v_info, uint32_t ti0, uint32_t ti1)
bool is_flipped (const Vec3f &new_vertex, uint32_t ti0, uint32_t ti1, const VertexInfo &v_info, const TriangleInfos &t_infos, const EdgeInfos &e_infos, const indexed_triangle_set &its)
bool degenerate (uint32_t vi, uint32_t ti0, uint32_t ti1, const VertexInfo &v_info, const EdgeInfos &e_infos, const Indices &indices)
bool create_no_volume (uint32_t vi0, uint32_t vi1, uint32_t ti0, uint32_t ti1, const VertexInfo &v_info0, const VertexInfo &v_info1, const EdgeInfos &e_infos, const Indices &indices)
Vec3d calculate_3errors (const Triangle &t, const Vertices &vertices, const VertexInfos &v_infos)
Error calculate_error (uint32_t ti, const Triangle &t, const Vertices &vertices, const VertexInfos &v_infos, unsigned char &min_index)
void remove_triangle (EdgeInfos &e_infos, VertexInfo &v_info, uint32_t ti)
void change_neighbors (EdgeInfos &e_infos, VertexInfos &v_infos, uint32_t ti0, uint32_t ti1, uint32_t vi0, uint32_t vi1, uint32_t vi_top0, const Triangle &t1, CopyEdgeInfos &infos, EdgeInfos &e_infos1)
void compact (const VertexInfos &v_infos, const TriangleInfos &t_infos, const EdgeInfos &e_infos, indexed_triangle_set &its)

Variables

const uint32_t check_cancel_period = 16
const size_t max_triangle_count_for_one_vertex = 50
const int status_init_size = 10
const int status_normal_size = 25
const int status_sum_quadric = 25
const int status_set_offsets = 10
const int status_calc_errors = 30
const int status_create_refs = 10

Typedef Documentation

◆ CopyEdgeInfos

◆ EdgeInfos

◆ Errors

using QuadricEdgeCollapse::Errors = std::vector<Error>

◆ Indices

using QuadricEdgeCollapse::Indices = std::vector<stl_triangle_vertex_indices>

◆ StatusFn

using QuadricEdgeCollapse::StatusFn = std::function<void(int)>

◆ ThrowOnCancel

using QuadricEdgeCollapse::ThrowOnCancel = std::function<void(void)>

◆ Triangle

using QuadricEdgeCollapse::Triangle = stl_triangle_vertex_indices

◆ TriangleInfos

◆ VertexInfos

◆ Vertices

using QuadricEdgeCollapse::Vertices = std::vector<stl_vertex>

Function Documentation

◆ calculate_3errors()

Vec3d QuadricEdgeCollapse::calculate_3errors ( const Triangle & t,
const Vertices & vertices,
const VertexInfos & v_infos )
710{
711 Vec3d error;
712 for (size_t j = 0; j < 3; ++j) {
713 size_t j2 = (j == 2) ? 0 : (j + 1);
714 uint32_t vi0 = t[j];
715 uint32_t vi1 = t[j2];
716 SymMat q(v_infos[vi0].q); // copy
717 q += v_infos[vi1].q;
718 error[j] = calculate_error(vi0, vi1, q, vertices);
719 }
720 return error;
721}
Definition QuadricEdgeCollapse.cpp:30
double calculate_error(uint32_t id_v1, uint32_t id_v2, const SymMat &q, const Vertices &vertices)
Definition QuadricEdgeCollapse.cpp:405
Eigen::Matrix< double, 3, 1, Eigen::DontAlign > Vec3d
Definition Point.hpp:68

References calculate_error().

Referenced by calculate_error(), and Slic3r::its_quadric_edge_collapse().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ calculate_determinant()

double QuadricEdgeCollapse::calculate_determinant ( const SymMat & q)
376{
377 return q.det(0, 1, 2, 1, 4, 5, 2, 5, 7);
378}
T det(int a11, int a12, int a13, int a21, int a22, int a23, int a31, int a32, int a33) const
Definition QuadricEdgeCollapse.cpp:49

References QuadricEdgeCollapse::SymMat::det().

Referenced by calculate_error(), and calculate_vertex().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ calculate_error() [1/2]

double QuadricEdgeCollapse::calculate_error ( uint32_t id_v1,
uint32_t id_v2,
const SymMat & q,
const Vertices & vertices )
409{
410 double det = calculate_determinant(q);
411 if (std::abs(det) < std::numeric_limits<double>::epsilon()) {
412 // can't divide by zero
413 auto verts = create_vertices(id_v1, id_v2, vertices);
414 auto errors = vertices_error(q, verts);
415 return *std::min_element(std::begin(errors), std::end(errors));
416 }
417 Vec3d vertex = calculate_vertex(det, q);
418 return vertex_error(q, vertex);
419}
double calculate_determinant(const SymMat &q)
Definition QuadricEdgeCollapse.cpp:375
double vertex_error(const SymMat &q, const Vec3d &vertex)
Definition QuadricEdgeCollapse.cpp:438
std::array< Vec3d, 3 > create_vertices(uint32_t id_v1, uint32_t id_v2, const Vertices &vertices)
Definition QuadricEdgeCollapse.cpp:388
Vec3f calculate_vertex(uint32_t id_v1, uint32_t id_v2, const SymMat &q, const Vertices &vertices)
Definition QuadricEdgeCollapse.cpp:422
std::array< double, 3 > vertices_error(const SymMat &q, const std::array< Vec3d, 3 > &vertices)
Definition QuadricEdgeCollapse.cpp:396

References calculate_determinant(), calculate_vertex(), create_vertices(), vertex_error(), and vertices_error().

Referenced by calculate_3errors(), and Slic3r::its_quadric_edge_collapse().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ calculate_error() [2/2]

Error QuadricEdgeCollapse::calculate_error ( uint32_t ti,
const Triangle & t,
const Vertices & vertices,
const VertexInfos & v_infos,
unsigned char & min_index )
728{
729 Vec3d error = calculate_3errors(t, vertices, v_infos);
730 // select min error
731 min_index = (error[0] < error[1]) ? ((error[0] < error[2]) ? 0 : 2) :
732 ((error[1] < error[2]) ? 1 : 2);
733 return Error(static_cast<float>(error[min_index]), ti);
734}
Vec3d calculate_3errors(const Triangle &t, const Vertices &vertices, const VertexInfos &v_infos)
Definition QuadricEdgeCollapse.cpp:707
@ Error
Definition LifecycleEvents.hpp:68

References calculate_3errors(), and Slic3r::Error.

Here is the call graph for this function:

◆ calculate_vertex() [1/2]

Vec3d QuadricEdgeCollapse::calculate_vertex ( double det,
const SymMat & q )
380 {
381 double det_1 = -1 / det;
382 double det_x = q.det(1, 2, 3, 4, 5, 6, 5, 7, 8); // vx = A41/det(q_delta)
383 double det_y = q.det(0, 2, 3, 1, 5, 6, 2, 7, 8); // vy = A42/det(q_delta)
384 double det_z = q.det(0, 1, 3, 1, 4, 6, 2, 5, 8); // vz = A43/det(q_delta)
385 return Vec3d(det_1 * det_x, -det_1 * det_y, det_1 * det_z);
386}

References QuadricEdgeCollapse::SymMat::det().

Here is the call graph for this function:

◆ calculate_vertex() [2/2]

Vec3f QuadricEdgeCollapse::calculate_vertex ( uint32_t id_v1,
uint32_t id_v2,
const SymMat & q,
const Vertices & vertices )
426{
427 double det = calculate_determinant(q);
428 if (std::abs(det) < std::numeric_limits<double>::epsilon()) {
429 // can't divide by zero
430 auto verts = create_vertices(id_v1, id_v2, vertices);
431 auto errors = vertices_error(q, verts);
432 auto mit = std::min_element(std::begin(errors), std::end(errors));
433 return verts[mit - std::begin(errors)].cast<float>();
434 }
435 return calculate_vertex(det, q).cast<float>();
436}

References calculate_determinant(), calculate_vertex(), create_vertices(), and vertices_error().

Referenced by calculate_error(), calculate_vertex(), and Slic3r::its_quadric_edge_collapse().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ change_neighbors()

void QuadricEdgeCollapse::change_neighbors ( EdgeInfos & e_infos,
VertexInfos & v_infos,
uint32_t ti0,
uint32_t ti1,
uint32_t vi0,
uint32_t vi1,
uint32_t vi_top0,
const Triangle & t1,
CopyEdgeInfos & infos,
EdgeInfos & e_infos1 )
764{
765 // have to copy Edge info from higher vertex index into smaller
766 assert(vi0 < vi1);
767
768 // vertex index of triangle 1 which is not vi0 nor vi1
769 uint32_t vi_top1 = t1[0];
770 if (vi_top1 == vi0 || vi_top1 == vi1) {
771 vi_top1 = t1[1];
772 if (vi_top1 == vi0 || vi_top1 == vi1) vi_top1 = t1[2];
773 }
774
775 remove_triangle(e_infos, v_infos[vi_top0], ti0);
776 remove_triangle(e_infos, v_infos[vi_top1], ti1);
777
778 VertexInfo &v_info0 = v_infos[vi0];
779 VertexInfo &v_info1 = v_infos[vi1];
780
781 uint32_t new_triangle_count = v_info0.count + v_info1.count - 4;
782 remove_triangle(e_infos, v_info0, ti0);
783 remove_triangle(e_infos, v_info0, ti1);
784
785 // copy second's edge infos out of e_infos, to free size
786 e_infos1.clear();
787 e_infos1.reserve(v_info1.count - 2);
788 uint32_t v_info_s_end = v_info1.start + v_info1.count;
789 for (uint32_t ei = v_info1.start; ei < v_info_s_end; ++ei) {
790 const EdgeInfo &e_info = e_infos[ei];
791 if (e_info.t_index == ti0) continue;
792 if (e_info.t_index == ti1) continue;
793 e_infos1.emplace_back(e_info);
794 }
795 v_info1.count = 0;
796
797 uint32_t need = (new_triangle_count < v_info0.count)? 0:
798 (new_triangle_count - v_info0.count);
799
800 uint32_t act_vi = vi0 + 1;
801 VertexInfo *act_v_info = &v_infos[act_vi];
802 uint32_t act_start = act_v_info->start;
803 uint32_t last_end = v_info0.start + v_info0.count;
804
805 infos.clear();
806 infos.reserve(need);
807
808 while (true) {
809 uint32_t save = act_start - last_end;
810 if (save > 0) {
811 if (save >= need) break;
812 need -= save;
813 infos.emplace_back(act_v_info->start, act_v_info->count, need);
814 } else {
815 infos.back().count += act_v_info->count;
816 }
817 last_end = act_v_info->start + act_v_info->count;
818 act_v_info->start += need;
819 ++act_vi;
820 if (act_vi < v_infos.size()) {
821 act_v_info = &v_infos[act_vi];
822 act_start = act_v_info->start;
823 } else
824 act_start = e_infos.size(); // fix for edge between last two triangles
825 }
826
827 // copy by c_infos
828 for (uint32_t i = infos.size(); i > 0; --i) {
829 const CopyEdgeInfo &c_info = infos[i - 1];
830 for (uint32_t ei = c_info.start + c_info.count - 1; ei >= c_info.start; --ei)
831 e_infos[ei + c_info.move] = e_infos[ei]; // copy
832 }
833
834 // copy triangle from first info into second
835 for (uint32_t ei_s = 0; ei_s < e_infos1.size(); ++ei_s) {
836 uint32_t ei_f = v_info0.start + v_info0.count;
837 e_infos[ei_f] = e_infos1[ei_s]; // copy
838 ++v_info0.count;
839 }
840}
static unsigned int count
Definition AuxiliaryDataViewModel.cpp:246
void save(Archive &archive, wxString const &d)
Definition GLGizmoEmboss.cpp:3403
void remove_triangle(EdgeInfos &e_infos, VertexInfo &v_info, uint32_t ti)
Definition QuadricEdgeCollapse.cpp:736
Definition QuadricEdgeCollapse.cpp:104
uint32_t t_index
Definition QuadricEdgeCollapse.cpp:105
Definition QuadricEdgeCollapse.cpp:97
uint32_t count
Definition QuadricEdgeCollapse.cpp:99
uint32_t start
Definition QuadricEdgeCollapse.cpp:99

References QuadricEdgeCollapse::CopyEdgeInfo::count, QuadricEdgeCollapse::VertexInfo::count, QuadricEdgeCollapse::CopyEdgeInfo::move, remove_triangle(), save(), QuadricEdgeCollapse::CopyEdgeInfo::start, QuadricEdgeCollapse::VertexInfo::start, and QuadricEdgeCollapse::EdgeInfo::t_index.

Referenced by Slic3r::its_quadric_edge_collapse().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ compact()

void QuadricEdgeCollapse::compact ( const VertexInfos & v_infos,
const TriangleInfos & t_infos,
const EdgeInfos & e_infos,
indexed_triangle_set & its )
846{
847 uint32_t vi_new = 0;
848 for (uint32_t vi = 0; vi < v_infos.size(); ++vi) {
849 const VertexInfo &v_info = v_infos[vi];
850 if (v_info.is_deleted()) continue; // deleted
851 uint32_t e_info_end = v_info.start + v_info.count;
852 for (uint32_t ei = v_info.start; ei < e_info_end; ++ei) {
853 const EdgeInfo &e_info = e_infos[ei];
854 // change vertex index
855 its.indices[e_info.t_index][e_info.edge] = vi_new;
856 }
857 // compact vertices
858 its.vertices[vi_new++] = its.vertices[vi];
859 }
860 // remove vertices tail
861 its.vertices.erase(its.vertices.begin() + vi_new, its.vertices.end());
862
863 uint32_t ti_new = 0;
864 for (uint32_t ti = 0; ti < t_infos.size(); ti++) {
865 const TriangleInfo &t_info = t_infos[ti];
866 if (t_info.is_deleted()) continue;
867 its.indices[ti_new++] = its.indices[ti];
868 }
869 its.indices.erase(its.indices.begin() + ti_new, its.indices.end());
870}
unsigned char edge
Definition QuadricEdgeCollapse.cpp:106
Definition QuadricEdgeCollapse.cpp:86
bool is_deleted() const
Definition QuadricEdgeCollapse.cpp:93
bool is_deleted() const
Definition QuadricEdgeCollapse.cpp:101

References QuadricEdgeCollapse::VertexInfo::count, QuadricEdgeCollapse::EdgeInfo::edge, QuadricEdgeCollapse::TriangleInfo::is_deleted(), QuadricEdgeCollapse::VertexInfo::is_deleted(), QuadricEdgeCollapse::VertexInfo::start, and QuadricEdgeCollapse::EdgeInfo::t_index.

Referenced by Slic3r::its_quadric_edge_collapse().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ create_no_volume()

bool QuadricEdgeCollapse::create_no_volume ( uint32_t vi0,
uint32_t vi1,
uint32_t ti0,
uint32_t ti1,
const VertexInfo & v_info0,
const VertexInfo & v_info1,
const EdgeInfos & e_infos,
const Indices & indices )
666{
667 // check that triangles around vertex0 doesn't have half edge
668 // with opposit order in set of triangles around vertex1
669 // protect from creation of two triangles with oposit order - no volume space
670 size_t v_info0_end = v_info0.start + v_info0.count - 2;
671 size_t v_info1_end = v_info1.start + v_info1.count - 2;
672 for (size_t ei0 = v_info0.start; ei0 < v_info0_end; ++ei0) {
673 const EdgeInfo &e_info0 = e_infos[ei0];
674 const Triangle &t0 = indices[e_info0.t_index];
675 // edge CCW vertex indices are t0vi0, t0vi1
676 size_t t0i = 0;
677 uint32_t t0vi0 = static_cast<uint32_t>(t0[t0i]);
678 if (t0vi0 == vi0) {
679 ++t0i;
680 t0vi0 = static_cast<uint32_t>(t0[t0i]);
681 }
682 ++t0i;
683 uint32_t t0vi1 = static_cast<uint32_t>(t0[t0i]);
684 if (t0vi1 == vi0) {
685 ++t0i;
686 t0vi1 = static_cast<uint32_t>(t0[t0i]);
687 }
688 for (size_t ei1 = v_info1.start; ei1 < v_info1_end; ++ei1) {
689 const EdgeInfo &e_info1 = e_infos[ei1];
690 const Triangle &t1 = indices[e_info1.t_index];
691 size_t t1i = 0;
692 for (; t1i < 3; ++t1i) if (static_cast<uint32_t>(t1[t1i]) == t0vi1) break;
693 if (t1i >= 3) continue; // without vertex index from triangle 0
694 // check if second index is same too
695 ++t1i;
696 if (t1i == 3) t1i = 0; // triangle loop(modulo 3)
697 if (static_cast<uint32_t>(t1[t1i]) == vi1) {
698 ++t1i;
699 if (t1i == 3) t1i = 0; // triangle loop(modulo 3)
700 }
701 if (static_cast<uint32_t>(t1[t1i]) == t0vi0) return true;
702 }
703 }
704 return false;
705}
stl_triangle_vertex_indices Triangle
Definition QuadricEdgeCollapse.cpp:68

References QuadricEdgeCollapse::VertexInfo::count, QuadricEdgeCollapse::VertexInfo::start, and QuadricEdgeCollapse::EdgeInfo::t_index.

Referenced by Slic3r::its_quadric_edge_collapse().

Here is the caller graph for this function:

◆ create_normal()

Vec3d QuadricEdgeCollapse::create_normal ( const Triangle & triangle,
const Vertices & vertices )
365{
366 Vec3d v0 = vertices[triangle[0]].cast<double>();
367 Vec3d v1 = vertices[triangle[1]].cast<double>();
368 Vec3d v2 = vertices[triangle[2]].cast<double>();
369 // n = triangle normal
370 Vec3d n = (v1 - v0).cross(v2 - v0);
371 n.normalize();
372 return n;
373}
T cross(const boost::geometry::model::d2::point_xy< T > &v1, const boost::geometry::model::d2::point_xy< T > &v2)
Definition ExtrusionSimulator.cpp:168

References Slic3r::cross().

Referenced by Slic3r::its_quadric_edge_collapse().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ create_quadric()

SymMat QuadricEdgeCollapse::create_quadric ( const Triangle & t,
const Vec3d & n,
const Vertices & vertices )
449{
450 Vec3d v0 = vertices[t[0]].cast<double>();
451 return SymMat(n.x(), n.y(), n.z(), -n.dot(v0));
452}

◆ create_vertices()

std::array< Vec3d, 3 > QuadricEdgeCollapse::create_vertices ( uint32_t id_v1,
uint32_t id_v2,
const Vertices & vertices )
389{
390 Vec3d v0 = vertices[id_v1].cast<double>();
391 Vec3d v1 = vertices[id_v2].cast<double>();
392 Vec3d vm = (v0 + v1) / 2.;
393 return {v0, v1, vm};
394}

Referenced by calculate_error(), and calculate_vertex().

Here is the caller graph for this function:

◆ degenerate()

bool QuadricEdgeCollapse::degenerate ( uint32_t vi,
uint32_t ti0,
uint32_t ti1,
const VertexInfo & v_info,
const EdgeInfos & e_infos,
const Indices & indices )
647{
648 // check surround triangle do not contain vertex index
649 // protect from creation of triangle with two same vertices inside
650 size_t v_info_end = v_info.start + v_info.count - 2;
651 for (size_t ei = v_info.start; ei < v_info_end; ++ei) {
652 assert(ei < e_infos.size());
653 const EdgeInfo &e_info = e_infos[ei];
654 const Triangle &t = indices[e_info.t_index];
655 for (size_t i = 0; i < 3; ++i)
656 if (static_cast<uint32_t>(t[i]) == vi) return true;
657 }
658 return false;
659}

References QuadricEdgeCollapse::VertexInfo::count, QuadricEdgeCollapse::VertexInfo::start, and QuadricEdgeCollapse::EdgeInfo::t_index.

Referenced by Slic3r::its_quadric_edge_collapse().

Here is the caller graph for this function:

◆ find_triangle_index1()

std::optional< uint32_t > QuadricEdgeCollapse::find_triangle_index1 ( uint32_t vi,
const VertexInfo & v_info,
uint32_t ti,
const EdgeInfos & e_infos,
const Indices & indices )
557{
558 coord_t vi_coord = static_cast<coord_t>(vi);
559 uint32_t end = v_info.start + v_info.count;
560 for (uint32_t ei = v_info.start; ei < end; ++ei) {
561 const EdgeInfo &e_info = e_infos[ei];
562 if (e_info.t_index == ti0) continue;
563 const Triangle& t = indices[e_info.t_index];
564 if (t[(e_info.edge + 1) % 3] == vi_coord ||
565 t[(e_info.edge + 2) % 3] == vi_coord)
566 return e_info.t_index;
567 }
568 // triangle0 is on border and do NOT have twin edge
569 return {};
570}
int64_t coord_t
Definition libslic3r.h:48

References QuadricEdgeCollapse::VertexInfo::count, QuadricEdgeCollapse::EdgeInfo::edge, QuadricEdgeCollapse::VertexInfo::start, and QuadricEdgeCollapse::EdgeInfo::t_index.

Referenced by Slic3r::its_quadric_edge_collapse().

Here is the caller graph for this function:

◆ init()

std::tuple< TriangleInfos, VertexInfos, EdgeInfos, Errors > QuadricEdgeCollapse::init ( const indexed_triangle_set & its,
ThrowOnCancel & throw_on_cancel,
StatusFn & status_fn )
456{
457 int status_offset = 0;
458 TriangleInfos t_infos(its.indices.size());
459 VertexInfos v_infos(its.vertices.size());
460 {
461 std::vector<SymMat> triangle_quadrics(its.indices.size());
462 // calculate normals
463 tbb::parallel_for(tbb::blocked_range<size_t>(0, its.indices.size()),
464 [&](const tbb::blocked_range<size_t> &range) {
465 for (size_t i = range.begin(); i < range.end(); ++i) {
466 const Triangle &t = its.indices[i];
467 TriangleInfo & t_info = t_infos[i];
468 Vec3d normal = create_normal(t, its.vertices);
469 t_info.n = normal.cast<float>();
470 triangle_quadrics[i] = create_quadric(t, normal, its.vertices);
471 if (i % 1000000 == 0) {
472 throw_on_cancel();
473 status_fn(status_offset + (i * status_normal_size) / its.indices.size());
474 }
475 }
476 }); // END parallel for
477 status_offset += status_normal_size;
478
479 // sum quadrics
480 for (size_t i = 0; i < its.indices.size(); i++) {
481 const Triangle &t = its.indices[i];
482 const SymMat & q = triangle_quadrics[i];
483 for (size_t e = 0; e < 3; e++) {
484 VertexInfo &v_info = v_infos[t[e]];
485 v_info.q += q;
486 ++v_info.count; // triangle count
487 }
488 if (i % 1000000 == 0) {
489 throw_on_cancel();
490 status_fn(status_offset + (i * status_sum_quadric) / its.indices.size());
491 }
492 }
493 status_offset += status_sum_quadric;
494 } // remove triangle quadrics
495
496 // set offseted starts
497 uint32_t triangle_start = 0;
498 for (VertexInfo &v_info : v_infos) {
499 v_info.start = triangle_start;
500 triangle_start += v_info.count;
501 // set filled vertex to zero
502 v_info.count = 0;
503 }
504 assert(its.indices.size() * 3 == triangle_start);
505
506 status_offset += status_set_offsets;
507 throw_on_cancel();
508 status_fn(status_offset);
509
510 // calc error
511 Errors errors(its.indices.size());
512 tbb::parallel_for(tbb::blocked_range<size_t>(0, its.indices.size()),
513 [&](const tbb::blocked_range<size_t> &range) {
514 for (size_t i = range.begin(); i < range.end(); ++i) {
515 const Triangle &t = its.indices[i];
516 TriangleInfo & t_info = t_infos[i];
517 errors[i] = calculate_error(i, t, its.vertices, v_infos, t_info.min_index);
518 if (i % 1000000 == 0) {
519 throw_on_cancel();
520 status_fn(status_offset + (i * status_calc_errors) / its.indices.size());
521 }
522 if (i % 1000000 == 0) throw_on_cancel();
523 }
524 }); // END parallel for
525
526 status_offset += status_calc_errors;
527
528 // create reference
529 EdgeInfos e_infos(its.indices.size() * 3);
530 for (size_t i = 0; i < its.indices.size(); i++) {
531 const Triangle &t = its.indices[i];
532 for (size_t j = 0; j < 3; ++j) {
533 VertexInfo &v_info = v_infos[t[j]];
534 size_t ei = v_info.start + v_info.count;
535 assert(ei < e_infos.size());
536 EdgeInfo &e_info = e_infos[ei];
537 e_info.t_index = i;
538 e_info.edge = j;
539 ++v_info.count;
540 }
541 if (i % 1000000 == 0) {
542 throw_on_cancel();
543 status_fn(status_offset + (i * status_create_refs) / its.indices.size());
544 }
545 }
546
547 throw_on_cancel();
548 status_fn(100);
549 return {t_infos, v_infos, e_infos, errors};
550}
const int status_create_refs
Definition QuadricEdgeCollapse.cpp:169
const int status_normal_size
Definition QuadricEdgeCollapse.cpp:165
std::vector< TriangleInfo > TriangleInfos
Definition QuadricEdgeCollapse.cpp:96
std::vector< Error > Errors
Definition QuadricEdgeCollapse.cpp:83
std::vector< EdgeInfo > EdgeInfos
Definition QuadricEdgeCollapse.cpp:109
const int status_calc_errors
Definition QuadricEdgeCollapse.cpp:168
const int status_set_offsets
Definition QuadricEdgeCollapse.cpp:167
std::vector< VertexInfo > VertexInfos
Definition QuadricEdgeCollapse.cpp:103
const int status_sum_quadric
Definition QuadricEdgeCollapse.cpp:166
auto range(Cont &&cont)
Definition libslic3r.h:405
SymMat q
Definition QuadricEdgeCollapse.cpp:98

References QuadricEdgeCollapse::VertexInfo::count, QuadricEdgeCollapse::VertexInfo::q, Slic3r::range(), status_normal_size, and status_sum_quadric.

Referenced by Slic3r::its_quadric_edge_collapse().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ is_flipped()

bool QuadricEdgeCollapse::is_flipped ( const Vec3f & new_vertex,
uint32_t ti0,
uint32_t ti1,
const VertexInfo & v_info,
const TriangleInfos & t_infos,
const EdgeInfos & e_infos,
const indexed_triangle_set & its )
611{
612 static const float thr_pos = 1.0f - std::numeric_limits<float>::epsilon();
613 static const float thr_neg = -thr_pos;
614 static const float dot_thr = 0.2f; // Value from simplify mesh cca 80 DEG
615
616 // for each vertex triangles
617 size_t v_info_end = v_info.start + v_info.count-2;
618 for (size_t ei = v_info.start; ei < v_info_end; ++ei) {
619 assert(ei < e_infos.size());
620 const EdgeInfo &e_info = e_infos[ei];
621 const Triangle &t = its.indices[e_info.t_index];
622 const Vec3f &normal = t_infos[e_info.t_index].n;
623 const Vec3f &vf = its.vertices[t[(e_info.edge + 1) % 3]];
624 const Vec3f &vs = its.vertices[t[(e_info.edge + 2) % 3]];
625
626 Vec3f d1 = vf - new_vertex;
627 d1.normalize();
628 Vec3f d2 = vs - new_vertex;
629 d2.normalize();
630
631 float dot = d1.dot(d2);
632 if (dot > thr_pos || dot < thr_neg) return true;
633 // IMPROVE: propagate new normal
634 Vec3f n = d1.cross(d2);
635 n.normalize();
636 if(n.dot(normal) < dot_thr) return true;
637 }
638 return false;
639}
Eigen::Matrix< float, 3, 1, Eigen::DontAlign > Vec3f
Definition Point.hpp:65
Point normal(Point pt, double scale)
Definition TreeSupport.cpp:112
T dot(const boost::geometry::model::d2::point_xy< T > &v1, const boost::geometry::model::d2::point_xy< T > &v2)
Definition ExtrusionSimulator.cpp:154

References QuadricEdgeCollapse::VertexInfo::count, Slic3r::dot(), QuadricEdgeCollapse::EdgeInfo::edge, Slic3r::normal(), QuadricEdgeCollapse::VertexInfo::start, and QuadricEdgeCollapse::EdgeInfo::t_index.

Referenced by Slic3r::its_quadric_edge_collapse().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ remove_triangle()

void QuadricEdgeCollapse::remove_triangle ( EdgeInfos & e_infos,
VertexInfo & v_info,
uint32_t ti )
739{
740 auto e_info = e_infos.begin() + v_info.start;
741 auto e_info_end = e_info + v_info.count - 1;
742 for (; e_info != e_info_end; ++e_info) {
743 if (e_info->t_index == ti) {
744 *e_info = *e_info_end;
745 --v_info.count;
746 return;
747 }
748 }
749 assert(e_info_end->t_index == ti);
750 // last triangle is ti
751 --v_info.count;
752}

References QuadricEdgeCollapse::VertexInfo::count, and QuadricEdgeCollapse::VertexInfo::start.

Referenced by change_neighbors().

Here is the caller graph for this function:

◆ reorder_edges()

void QuadricEdgeCollapse::reorder_edges ( EdgeInfos & e_infos,
const VertexInfo & v_info,
uint32_t ti0,
uint32_t ti1 )
576{
577 // swap edge info of ti0 and ti1 to end(last one and one before)
578 size_t v_info_end = v_info.start + v_info.count - 2;
579 EdgeInfo &e_info_ti0 = e_infos[v_info_end];
580 EdgeInfo &e_info_ti1 = e_infos[v_info_end+1];
581 bool is_swaped = false;
582 for (size_t ei = v_info.start; ei < v_info_end; ++ei) {
583 EdgeInfo &e_info = e_infos[ei];
584 if (e_info.t_index == ti0) {
585 std::swap(e_info, e_info_ti0);
586 if (is_swaped) return;
587 if (e_info.t_index == ti1) {
588 std::swap(e_info, e_info_ti1);
589 return;
590 }
591 is_swaped = true;
592 } else if (e_info.t_index == ti1) {
593 std::swap(e_info, e_info_ti1);
594 if (is_swaped) return;
595 if (e_info.t_index == ti0) {
596 std::swap(e_info, e_info_ti0);
597 return;
598 }
599 is_swaped = true;
600 }
601 }
602}

References QuadricEdgeCollapse::VertexInfo::count, QuadricEdgeCollapse::VertexInfo::start, and QuadricEdgeCollapse::EdgeInfo::t_index.

Referenced by Slic3r::its_quadric_edge_collapse().

Here is the caller graph for this function:

◆ vertex_error()

double QuadricEdgeCollapse::vertex_error ( const SymMat & q,
const Vec3d & vertex )
439{
440 const double &x = vertex.x(), &y = vertex.y(), &z = vertex.z();
441 return q[0] * x * x + 2 * q[1] * x * y + 2 * q[2] * x * z +
442 2 * q[3] * x + q[4] * y * y + 2 * q[5] * y * z +
443 2 * q[6] * y + q[7] * z * z + 2 * q[8] * z + q[9];
444}

Referenced by calculate_error(), and vertices_error().

Here is the caller graph for this function:

◆ vertices_error()

std::array< double, 3 > QuadricEdgeCollapse::vertices_error ( const SymMat & q,
const std::array< Vec3d, 3 > & vertices )
398{
399 return {
400 vertex_error(q, vertices[0]),
401 vertex_error(q, vertices[1]),
402 vertex_error(q, vertices[2])};
403}

References vertex_error().

Referenced by calculate_error(), and calculate_vertex().

Here is the call graph for this function:
Here is the caller graph for this function:

Variable Documentation

◆ check_cancel_period

const uint32_t QuadricEdgeCollapse::check_cancel_period = 16

◆ max_triangle_count_for_one_vertex

const size_t QuadricEdgeCollapse::max_triangle_count_for_one_vertex = 50

◆ status_calc_errors

const int QuadricEdgeCollapse::status_calc_errors = 30

◆ status_create_refs

const int QuadricEdgeCollapse::status_create_refs = 10

◆ status_init_size

const int QuadricEdgeCollapse::status_init_size = 10

◆ status_normal_size

const int QuadricEdgeCollapse::status_normal_size = 25

Referenced by init().

◆ status_set_offsets

const int QuadricEdgeCollapse::status_set_offsets = 10

◆ status_sum_quadric

const int QuadricEdgeCollapse::status_sum_quadric = 25

Referenced by init().