diff --git a/src/libslic3r/Orient.cpp b/src/libslic3r/Orient.cpp index f3a6edfff6..b7a6d619e6 100644 --- a/src/libslic3r/Orient.cpp +++ b/src/libslic3r/Orient.cpp @@ -57,16 +57,19 @@ namespace orientation { // management and spatial index structures for acceleration. class AutoOrienter { public: + int face_count_hull; OrientMesh *orient_mesh = NULL; TriangleMesh* mesh; TriangleMesh mesh_convex_hull; - Eigen::MatrixXf normals, normals_hull; + Eigen::MatrixXf normals, normals_quantize, normals_hull, normals_hull_quantize; Eigen::VectorXf areas, areas_hull; Eigen::VectorXf is_apperance; // whether a facet is outer apperance Eigen::MatrixXf z_projected; Eigen::VectorXf z_max, z_max_hull; // max of projected z Eigen::VectorXf z_median; // median of projected z Eigen::VectorXf z_mean; // mean of projected z + std::vector face_normals; + std::vector face_normals_hull; OrientParams params; @@ -111,9 +114,9 @@ public: { orientations = { { 0,0,-1 } }; // original orientation - area_cumulation(normals, areas, 10); + area_cumulation_accurate(face_normals, normals_quantize, areas, 10); - area_cumulation(normals_hull, areas_hull, 10); + area_cumulation_accurate(face_normals_hull, normals_hull_quantize, areas_hull, 10); add_supplements(); @@ -181,17 +184,16 @@ public: { int face_count = mesh->facets_count(); auto its = mesh->its; - auto face_normals = its_face_normals(its); + face_normals = its_face_normals(its); areas = Eigen::VectorXf::Zero(face_count); is_apperance = Eigen::VectorXf::Zero(face_count); normals = Eigen::MatrixXf::Zero(face_count, 3); + normals_quantize = Eigen::MatrixXf::Zero(face_count, 3); for (size_t i = 0; i < face_count; i++) { float area = its.facet_area(i); - if (params.NEGL_FACE_SIZE > 0 && area < params.NEGL_FACE_SIZE) - continue; - - normals.row(i) = quantize_vec3f(face_normals[i]); + normals.row(i) = face_normals[i]; + normals_quantize.row(i) = quantize_vec3f(face_normals[i]); areas(i) = area; is_apperance(i) = (its.get_property(i).type == EnumFaceTypes::eExteriorAppearance); count_apperance += (is_apperance(i)==1); @@ -208,17 +210,17 @@ public: int face_count = mesh_convex_hull.facets_count(); auto its = mesh_convex_hull.its; - auto face_normals = its_face_normals(its); + face_count_hull = mesh_convex_hull.facets_count(); + face_normals_hull = its_face_normals(its); areas_hull = Eigen::VectorXf::Zero(face_count); - normals_hull = Eigen::MatrixXf::Zero(face_count, 3); + normals_hull = Eigen::MatrixXf::Zero(face_count_hull, 3); + normals_hull_quantize = Eigen::MatrixXf::Zero(face_count_hull, 3); for (size_t i = 0; i < face_count; i++) { float area = its.facet_area(i); - if (params.NEGL_FACE_SIZE > 0 && area < params.NEGL_FACE_SIZE) - continue; - //normals_hull.row(i) = quantize_vec3f(face_normals[i]); //We cannot use quantized vector here, the accumulated error will result in bad orientations. - normals_hull.row(i) = face_normals[i]; + normals_hull.row(i) = face_normals_hull[i]; + normals_hull_quantize.row(i) = quantize_vec3f(face_normals_hull[i]); areas_hull(i) = area; } } @@ -248,7 +250,37 @@ public: BOOST_LOG_TRIVIAL(debug) << align_counts[i].first.transpose() << ", area: " << align_counts[i].second; } } + //This function is to make sure to return the accurate normal rather than quantized normal + void area_cumulation_accurate( std::vector& normals_, const Eigen::MatrixXf& quantize_normals_, const Eigen::VectorXf& areas_, int num_directions = 10) + { + std::unordered_map, Vec3f>, VecHash> alignments_; + Vec3f n1 = { 0, 0, 0 }; + std::vector current_areas = {0, 0}; + // init to 0 + for (size_t i = 0; i < areas_.size(); i++) { + alignments_.insert(std::pair(quantize_normals_.row(i), std::pair(current_areas, n1))); + } + // cumulate areas + for (size_t i = 0; i < areas_.size(); i++) + { + alignments_[quantize_normals_.row(i)].first[1] += areas_(i); + if (areas_(i) > alignments_[quantize_normals_.row(i)].first[0]){ + alignments_[quantize_normals_.row(i)].second = normals_[i]; + alignments_[quantize_normals_.row(i)].first[0] = areas_(i); + } + } + typedef std::pair, Vec3f>> PAIR; + std::vector align_counts(alignments_.begin(), alignments_.end()); + sort(align_counts.begin(), align_counts.end(), [](const PAIR& p1, const PAIR& p2) {return p1.second.first[1] > p2.second.first[1]; }); + + num_directions = std::min((size_t)num_directions, align_counts.size()); + for (size_t i = 0; i < num_directions; i++) + { + orientations.push_back(align_counts[i].second.second); + BOOST_LOG_TRIVIAL(debug) << align_counts[i].second.second.transpose() << ", area: " << align_counts[i].second.first[1]; + } + } void add_supplements() { std::vector vecs = { {0, 0, -1} ,{0.70710678, 0, -0.70710678},{0, 0.70710678, -0.70710678}, @@ -264,7 +296,7 @@ public: /// remove duplicate orientations /// /// tolerance. default 0.01 =sin(0.57\degree) - void remove_duplicates(double tol=0.00000001) + void remove_duplicates(double tol=0.0000001) { for (auto it = orientations.begin()+1; it < orientations.end(); ) {