Prusa Slicer 2.6.0
Loading...
Searching...
No Matches
QuadricEdgeCollapse Namespace Reference

Classes

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

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, Errorsinit (const indexed_triangle_set &its, ThrowOnCancel &throw_on_cancel, StatusFn &status_fn)
 
std::optional< uint32_tfind_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

using QuadricEdgeCollapse::CopyEdgeInfos = typedef std::vector<CopyEdgeInfo>

◆ EdgeInfos

using QuadricEdgeCollapse::EdgeInfos = typedef std::vector<EdgeInfo>

◆ Errors

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

◆ Indices

◆ StatusFn

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

◆ ThrowOnCancel

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

◆ Triangle

◆ TriangleInfos

using QuadricEdgeCollapse::TriangleInfos = typedef std::vector<TriangleInfo>

◆ VertexInfos

using QuadricEdgeCollapse::VertexInfos = typedef std::vector<VertexInfo>

◆ Vertices

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

Function Documentation

◆ calculate_3errors()

Vec3d QuadricEdgeCollapse::calculate_3errors ( const Triangle t,
const Vertices vertices,
const VertexInfos v_infos 
)
704{
705 Vec3d error;
706 for (size_t j = 0; j < 3; ++j) {
707 size_t j2 = (j == 2) ? 0 : (j + 1);
708 uint32_t vi0 = t[j];
709 uint32_t vi1 = t[j2];
710 SymMat q(v_infos[vi0].q); // copy
711 q += v_infos[vi1].q;
712 error[j] = calculate_error(vi0, vi1, q, vertices);
713 }
714 return error;
715}
Definition QuadricEdgeCollapse.cpp:16
double calculate_error(uint32_t id_v1, uint32_t id_v2, const SymMat &q, const Vertices &vertices)
Definition QuadricEdgeCollapse.cpp:391
static char error[256]
Definition tga.cpp:50
unsigned __int32 uint32_t
Definition unistd.h:79

References calculate_error(), and 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)
362{
363 return q.det(0, 1, 2, 1, 4, 5, 2, 5, 7);
364}
T det(int a11, int a12, int a13, int a21, int a22, int a23, int a31, int a32, int a33) const
Definition QuadricEdgeCollapse.cpp:35

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 
)
395{
396 double det = calculate_determinant(q);
397 if (std::abs(det) < std::numeric_limits<double>::epsilon()) {
398 // can't divide by zero
399 auto verts = create_vertices(id_v1, id_v2, vertices);
400 auto errors = vertices_error(q, verts);
401 return *std::min_element(std::begin(errors), std::end(errors));
402 }
403 Vec3d vertex = calculate_vertex(det, q);
404 return vertex_error(q, vertex);
405}
double calculate_determinant(const SymMat &q)
Definition QuadricEdgeCollapse.cpp:361
double vertex_error(const SymMat &q, const Vec3d &vertex)
Definition QuadricEdgeCollapse.cpp:424
std::array< Vec3d, 3 > create_vertices(uint32_t id_v1, uint32_t id_v2, const Vertices &vertices)
Definition QuadricEdgeCollapse.cpp:374
Vec3f calculate_vertex(uint32_t id_v1, uint32_t id_v2, const SymMat &q, const Vertices &vertices)
Definition QuadricEdgeCollapse.cpp:408
std::array< double, 3 > vertices_error(const SymMat &q, const std::array< Vec3d, 3 > &vertices)
Definition QuadricEdgeCollapse.cpp:382

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 
)
722{
723 Vec3d error = calculate_3errors(t, vertices, v_infos);
724 // select min error
725 min_index = (error[0] < error[1]) ? ((error[0] < error[2]) ? 0 : 2) :
726 ((error[1] < error[2]) ? 1 : 2);
727 return Error(static_cast<float>(error[min_index]), ti);
728}
Vec3d calculate_3errors(const Triangle &t, const Vertices &vertices, const VertexInfos &v_infos)
Definition QuadricEdgeCollapse.cpp:701
Definition QuadricEdgeCollapse.cpp:60

References calculate_3errors(), and error.

+ Here is the call graph for this function:

◆ calculate_vertex() [1/2]

Vec3d QuadricEdgeCollapse::calculate_vertex ( double  det,
const SymMat q 
)
366 {
367 double det_1 = -1 / det;
368 double det_x = q.det(1, 2, 3, 4, 5, 6, 5, 7, 8); // vx = A41/det(q_delta)
369 double det_y = q.det(0, 2, 3, 1, 5, 6, 2, 7, 8); // vy = A42/det(q_delta)
370 double det_z = q.det(0, 1, 3, 1, 4, 6, 2, 5, 8); // vz = A43/det(q_delta)
371 return Vec3d(det_1 * det_x, -det_1 * det_y, det_1 * det_z);
372}
Eigen::Matrix< double, 3, 1, Eigen::DontAlign > Vec3d
Definition Point.hpp:52

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 
)
412{
413 double det = calculate_determinant(q);
414 if (std::abs(det) < std::numeric_limits<double>::epsilon()) {
415 // can't divide by zero
416 auto verts = create_vertices(id_v1, id_v2, vertices);
417 auto errors = vertices_error(q, verts);
418 auto mit = std::min_element(std::begin(errors), std::end(errors));
419 return verts[mit - std::begin(errors)].cast<float>();
420 }
421 return calculate_vertex(det, q).cast<float>();
422}

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 
)
758{
759 // have to copy Edge info from higher vertex index into smaller
760 assert(vi0 < vi1);
761
762 // vertex index of triangle 1 which is not vi0 nor vi1
763 uint32_t vi_top1 = t1[0];
764 if (vi_top1 == vi0 || vi_top1 == vi1) {
765 vi_top1 = t1[1];
766 if (vi_top1 == vi0 || vi_top1 == vi1) vi_top1 = t1[2];
767 }
768
769 remove_triangle(e_infos, v_infos[vi_top0], ti0);
770 remove_triangle(e_infos, v_infos[vi_top1], ti1);
771
772 VertexInfo &v_info0 = v_infos[vi0];
773 VertexInfo &v_info1 = v_infos[vi1];
774
775 uint32_t new_triangle_count = v_info0.count + v_info1.count - 4;
776 remove_triangle(e_infos, v_info0, ti0);
777 remove_triangle(e_infos, v_info0, ti1);
778
779 // copy second's edge infos out of e_infos, to free size
780 e_infos1.clear();
781 e_infos1.reserve(v_info1.count - 2);
782 uint32_t v_info_s_end = v_info1.start + v_info1.count;
783 for (uint32_t ei = v_info1.start; ei < v_info_s_end; ++ei) {
784 const EdgeInfo &e_info = e_infos[ei];
785 if (e_info.t_index == ti0) continue;
786 if (e_info.t_index == ti1) continue;
787 e_infos1.emplace_back(e_info);
788 }
789 v_info1.count = 0;
790
791 uint32_t need = (new_triangle_count < v_info0.count)? 0:
792 (new_triangle_count - v_info0.count);
793
794 uint32_t act_vi = vi0 + 1;
795 VertexInfo *act_v_info = &v_infos[act_vi];
796 uint32_t act_start = act_v_info->start;
797 uint32_t last_end = v_info0.start + v_info0.count;
798
799 infos.clear();
800 infos.reserve(need);
801
802 while (true) {
803 uint32_t save = act_start - last_end;
804 if (save > 0) {
805 if (save >= need) break;
806 need -= save;
807 infos.emplace_back(act_v_info->start, act_v_info->count, need);
808 } else {
809 infos.back().count += act_v_info->count;
810 }
811 last_end = act_v_info->start + act_v_info->count;
812 act_v_info->start += need;
813 ++act_vi;
814 if (act_vi < v_infos.size()) {
815 act_v_info = &v_infos[act_vi];
816 act_start = act_v_info->start;
817 } else
818 act_start = e_infos.size(); // fix for edge between last two triangles
819 }
820
821 // copy by c_infos
822 for (uint32_t i = infos.size(); i > 0; --i) {
823 const CopyEdgeInfo &c_info = infos[i - 1];
824 for (uint32_t ei = c_info.start + c_info.count - 1; ei >= c_info.start; --ei)
825 e_infos[ei + c_info.move] = e_infos[ei]; // copy
826 }
827
828 // copy triangle from first info into second
829 for (uint32_t ei_s = 0; ei_s < e_infos1.size(); ++ei_s) {
830 uint32_t ei_f = v_info0.start + v_info0.count;
831 e_infos[ei_f] = e_infos1[ei_s]; // copy
832 ++v_info0.count;
833 }
834}
void save(Archive &archive, wxString const &d)
Definition GLGizmoEmboss.cpp:1557
void remove_triangle(EdgeInfos &e_infos, VertexInfo &v_info, uint32_t ti)
Definition QuadricEdgeCollapse.cpp:730
IGL_INLINE void count(const Eigen::SparseMatrix< XType > &X, const int dim, Eigen::SparseVector< SType > &S)
Definition count.cpp:12
Definition QuadricEdgeCollapse.cpp:98
uint32_t move
Definition QuadricEdgeCollapse.cpp:101
uint32_t count
Definition QuadricEdgeCollapse.cpp:100
uint32_t start
Definition QuadricEdgeCollapse.cpp:99
Definition QuadricEdgeCollapse.cpp:90
uint32_t t_index
Definition QuadricEdgeCollapse.cpp:91
Definition QuadricEdgeCollapse.cpp:83
uint32_t count
Definition QuadricEdgeCollapse.cpp:85
uint32_t start
Definition QuadricEdgeCollapse.cpp:85

References QuadricEdgeCollapse::VertexInfo::count, QuadricEdgeCollapse::CopyEdgeInfo::count, QuadricEdgeCollapse::CopyEdgeInfo::move, remove_triangle(), save(), QuadricEdgeCollapse::VertexInfo::start, QuadricEdgeCollapse::CopyEdgeInfo::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 
)
840{
841 uint32_t vi_new = 0;
842 for (uint32_t vi = 0; vi < v_infos.size(); ++vi) {
843 const VertexInfo &v_info = v_infos[vi];
844 if (v_info.is_deleted()) continue; // deleted
845 uint32_t e_info_end = v_info.start + v_info.count;
846 for (uint32_t ei = v_info.start; ei < e_info_end; ++ei) {
847 const EdgeInfo &e_info = e_infos[ei];
848 // change vertex index
849 its.indices[e_info.t_index][e_info.edge] = vi_new;
850 }
851 // compact vertices
852 its.vertices[vi_new++] = its.vertices[vi];
853 }
854 // remove vertices tail
855 its.vertices.erase(its.vertices.begin() + vi_new, its.vertices.end());
856
857 uint32_t ti_new = 0;
858 for (uint32_t ti = 0; ti < t_infos.size(); ti++) {
859 const TriangleInfo &t_info = t_infos[ti];
860 if (t_info.is_deleted()) continue;
861 its.indices[ti_new++] = its.indices[ti];
862 }
863 its.indices.erase(its.indices.begin() + ti_new, its.indices.end());
864}
unsigned char edge
Definition QuadricEdgeCollapse.cpp:92
Definition QuadricEdgeCollapse.cpp:72
bool is_deleted() const
Definition QuadricEdgeCollapse.cpp:79
bool is_deleted() const
Definition QuadricEdgeCollapse.cpp:87
std::vector< stl_vertex > vertices
Definition stl.h:165
std::vector< stl_triangle_vertex_indices > indices
Definition stl.h:164

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

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

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 
)
351{
352 Vec3d v0 = vertices[triangle[0]].cast<double>();
353 Vec3d v1 = vertices[triangle[1]].cast<double>();
354 Vec3d v2 = vertices[triangle[2]].cast<double>();
355 // n = triangle normal
356 Vec3d n = (v1 - v0).cross(v2 - v0);
357 n.normalize();
358 return n;
359}
T cross(const boost::geometry::model::d2::point_xy< T > &v1, const boost::geometry::model::d2::point_xy< T > &v2)
Definition ExtrusionSimulator.cpp:157

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 
)
435{
436 Vec3d v0 = vertices[t[0]].cast<double>();
437 return SymMat(n.x(), n.y(), n.z(), -n.dot(v0));
438}

◆ create_vertices()

std::array< Vec3d, 3 > QuadricEdgeCollapse::create_vertices ( uint32_t  id_v1,
uint32_t  id_v2,
const Vertices vertices 
)
375{
376 Vec3d v0 = vertices[id_v1].cast<double>();
377 Vec3d v1 = vertices[id_v2].cast<double>();
378 Vec3d vm = (v0 + v1) / 2.;
379 return {v0, v1, vm};
380}

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 
)
641{
642 // check surround triangle do not contain vertex index
643 // protect from creation of triangle with two same vertices inside
644 size_t v_info_end = v_info.start + v_info.count - 2;
645 for (size_t ei = v_info.start; ei < v_info_end; ++ei) {
646 assert(ei < e_infos.size());
647 const EdgeInfo &e_info = e_infos[ei];
648 const Triangle &t = indices[e_info.t_index];
649 for (size_t i = 0; i < 3; ++i)
650 if (static_cast<uint32_t>(t[i]) == vi) return true;
651 }
652 return false;
653}

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 
)
543{
544 coord_t vi_coord = static_cast<coord_t>(vi);
545 uint32_t end = v_info.start + v_info.count;
546 for (uint32_t ei = v_info.start; ei < end; ++ei) {
547 const EdgeInfo &e_info = e_infos[ei];
548 if (e_info.t_index == ti0) continue;
549 const Triangle& t = indices[e_info.t_index];
550 if (t[(e_info.edge + 1) % 3] == vi_coord ||
551 t[(e_info.edge + 2) % 3] == vi_coord)
552 return e_info.t_index;
553 }
554 // triangle0 is on border and do NOT have twin edge
555 return {};
556}
int32_t coord_t
Definition libslic3r.h:39

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 
)
442{
443 int status_offset = 0;
444 TriangleInfos t_infos(its.indices.size());
445 VertexInfos v_infos(its.vertices.size());
446 {
447 std::vector<SymMat> triangle_quadrics(its.indices.size());
448 // calculate normals
449 tbb::parallel_for(tbb::blocked_range<size_t>(0, its.indices.size()),
450 [&](const tbb::blocked_range<size_t> &range) {
451 for (size_t i = range.begin(); i < range.end(); ++i) {
452 const Triangle &t = its.indices[i];
453 TriangleInfo & t_info = t_infos[i];
454 Vec3d normal = create_normal(t, its.vertices);
455 t_info.n = normal.cast<float>();
456 triangle_quadrics[i] = create_quadric(t, normal, its.vertices);
457 if (i % 1000000 == 0) {
458 throw_on_cancel();
459 status_fn(status_offset + (i * status_normal_size) / its.indices.size());
460 }
461 }
462 }); // END parallel for
463 status_offset += status_normal_size;
464
465 // sum quadrics
466 for (size_t i = 0; i < its.indices.size(); i++) {
467 const Triangle &t = its.indices[i];
468 const SymMat & q = triangle_quadrics[i];
469 for (size_t e = 0; e < 3; e++) {
470 VertexInfo &v_info = v_infos[t[e]];
471 v_info.q += q;
472 ++v_info.count; // triangle count
473 }
474 if (i % 1000000 == 0) {
475 throw_on_cancel();
476 status_fn(status_offset + (i * status_sum_quadric) / its.indices.size());
477 }
478 }
479 status_offset += status_sum_quadric;
480 } // remove triangle quadrics
481
482 // set offseted starts
483 uint32_t triangle_start = 0;
484 for (VertexInfo &v_info : v_infos) {
485 v_info.start = triangle_start;
486 triangle_start += v_info.count;
487 // set filled vertex to zero
488 v_info.count = 0;
489 }
490 assert(its.indices.size() * 3 == triangle_start);
491
492 status_offset += status_set_offsets;
493 throw_on_cancel();
494 status_fn(status_offset);
495
496 // calc error
497 Errors errors(its.indices.size());
498 tbb::parallel_for(tbb::blocked_range<size_t>(0, its.indices.size()),
499 [&](const tbb::blocked_range<size_t> &range) {
500 for (size_t i = range.begin(); i < range.end(); ++i) {
501 const Triangle &t = its.indices[i];
502 TriangleInfo & t_info = t_infos[i];
503 errors[i] = calculate_error(i, t, its.vertices, v_infos, t_info.min_index);
504 if (i % 1000000 == 0) {
505 throw_on_cancel();
506 status_fn(status_offset + (i * status_calc_errors) / its.indices.size());
507 }
508 if (i % 1000000 == 0) throw_on_cancel();
509 }
510 }); // END parallel for
511
512 status_offset += status_calc_errors;
513
514 // create reference
515 EdgeInfos e_infos(its.indices.size() * 3);
516 for (size_t i = 0; i < its.indices.size(); i++) {
517 const Triangle &t = its.indices[i];
518 for (size_t j = 0; j < 3; ++j) {
519 VertexInfo &v_info = v_infos[t[j]];
520 size_t ei = v_info.start + v_info.count;
521 assert(ei < e_infos.size());
522 EdgeInfo &e_info = e_infos[ei];
523 e_info.t_index = i;
524 e_info.edge = j;
525 ++v_info.count;
526 }
527 if (i % 1000000 == 0) {
528 throw_on_cancel();
529 status_fn(status_offset + (i * status_create_refs) / its.indices.size());
530 }
531 }
532
533 throw_on_cancel();
534 status_fn(100);
535 return {t_infos, v_infos, e_infos, errors};
536}
const int status_create_refs
Definition QuadricEdgeCollapse.cpp:155
const int status_normal_size
Definition QuadricEdgeCollapse.cpp:151
const int status_calc_errors
Definition QuadricEdgeCollapse.cpp:154
const int status_set_offsets
Definition QuadricEdgeCollapse.cpp:153
std::vector< Error > Errors
Definition QuadricEdgeCollapse.cpp:69
std::vector< VertexInfo > VertexInfos
Definition QuadricEdgeCollapse.cpp:89
std::vector< EdgeInfo > EdgeInfos
Definition QuadricEdgeCollapse.cpp:95
const int status_sum_quadric
Definition QuadricEdgeCollapse.cpp:152
std::vector< TriangleInfo > TriangleInfos
Definition QuadricEdgeCollapse.cpp:82
auto range(Cont &&cont)
Definition libslic3r.h:356
SymMat q
Definition QuadricEdgeCollapse.cpp:84

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

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 
)
597{
598 static const float triangle_beauty_threshold = 1.0f - std::numeric_limits<float>::epsilon();
599 static const float dot_thr = 0.2f; // Value from simplify mesh cca 80 DEG
600
601 // for each vertex triangles
602 size_t v_info_end = v_info.start + v_info.count-2;
603 for (size_t ei = v_info.start; ei < v_info_end; ++ei) {
604 assert(ei < e_infos.size());
605 const EdgeInfo &e_info = e_infos[ei];
606 const Triangle &t = its.indices[e_info.t_index];
607 const Vec3f &normal = t_infos[e_info.t_index].n;
608 const Vec3f &vf = its.vertices[t[(e_info.edge + 1) % 3]];
609 const Vec3f &vs = its.vertices[t[(e_info.edge + 2) % 3]];
610
611 Vec3f d1 = vf - new_vertex;
612 d1.normalize();
613 Vec3f d2 = vs - new_vertex;
614 d2.normalize();
615
616 float dot = d1.dot(d2);
617 if (dot > triangle_beauty_threshold || dot < -triangle_beauty_threshold) { // OK, the new triangle is suspiciously ugly, but it can still be better than the original
618 const Vec3f &v_orig = its.vertices[t[(e_info.edge) % 3]];
619 Vec3f d1_orig = vf - v_orig;
620 d1_orig.normalize();
621 Vec3f d2_orig = vs - v_orig;
622 d2_orig.normalize();
623 if (std::fabs(d1_orig.dot(d2_orig)) < std::fabs(dot)) { // original was not that ugly, so return flipped
624 return true;
625 } // else original triangle was worse than the new, so don't discard the new yet
626 }
627 // IMPROVE: propagate new normal
628 Vec3f n = d1.cross(d2);
629 n.normalize();
630 if(n.dot(normal) < dot_thr) return true;
631 }
632 return false;
633}
T dot(const boost::geometry::model::d2::point_xy< T > &v1, const boost::geometry::model::d2::point_xy< T > &v2)
Definition ExtrusionSimulator.cpp:143

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

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 
)
733{
734 auto e_info = e_infos.begin() + v_info.start;
735 auto e_info_end = e_info + v_info.count - 1;
736 for (; e_info != e_info_end; ++e_info) {
737 if (e_info->t_index == ti) {
738 *e_info = *e_info_end;
739 --v_info.count;
740 return;
741 }
742 }
743 assert(e_info_end->t_index == ti);
744 // last triangle is ti
745 --v_info.count;
746}

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 
)
562{
563 // swap edge info of ti0 and ti1 to end(last one and one before)
564 size_t v_info_end = v_info.start + v_info.count - 2;
565 EdgeInfo &e_info_ti0 = e_infos[v_info_end];
566 EdgeInfo &e_info_ti1 = e_infos[v_info_end+1];
567 bool is_swaped = false;
568 for (size_t ei = v_info.start; ei < v_info_end; ++ei) {
569 EdgeInfo &e_info = e_infos[ei];
570 if (e_info.t_index == ti0) {
571 std::swap(e_info, e_info_ti0);
572 if (is_swaped) return;
573 if (e_info.t_index == ti1) {
574 std::swap(e_info, e_info_ti1);
575 return;
576 }
577 is_swaped = true;
578 } else if (e_info.t_index == ti1) {
579 std::swap(e_info, e_info_ti1);
580 if (is_swaped) return;
581 if (e_info.t_index == ti0) {
582 std::swap(e_info, e_info_ti0);
583 return;
584 }
585 is_swaped = true;
586 }
587 }
588}

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 
)
425{
426 const double &x = vertex.x(), &y = vertex.y(), &z = vertex.z();
427 return q[0] * x * x + 2 * q[1] * x * y + 2 * q[2] * x * z +
428 2 * q[3] * x + q[4] * y * y + 2 * q[5] * y * z +
429 2 * q[6] * y + q[7] * z * z + 2 * q[8] * z + q[9];
430}

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 
)
384{
385 return {
386 vertex_error(q, vertices[0]),
387 vertex_error(q, vertices[1]),
388 vertex_error(q, vertices[2])};
389}

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().