diff --git a/CgMath/CgPointWrangler.h b/CgMath/CgPointWrangler.h index 7b04f3dc887257652919d34744f507b7e1cb8d81..ba1be38afba82cb5dce259ff2df676efa0015735 100644 --- a/CgMath/CgPointWrangler.h +++ b/CgMath/CgPointWrangler.h @@ -4,6 +4,7 @@ // stl #include <vector> #include <queue> +#include <deque> #include <limits> #include <string> #include <algorithm> @@ -313,38 +314,46 @@ inline std::vector<std::pair<unsigned int, unsigned int>> CgPointWrangler::makeN } visited[max_y_index] = true; - // stack of point indices to process next - std::vector<unsigned int> stack; // record the "best" parent found for each vertex std::vector<std::pair<unsigned int, double>> scores; scores.resize(pca.size()); + // queue of point indices to process next + std::vector<unsigned int> queue; + + auto cmp = [&](const unsigned int left, unsigned int right) { + return scores[left].second > scores[right].second; + }; + auto visit = [&](unsigned int curr) { glm::vec3 normal = pca[curr].evec0; + glm::vec3 point = pca[curr].centroid; + double rad = pca[curr].radius2; // retrieve neighbourhood indices auto curr_nh_ind = neighbourhoods[curr]; // find out which of the neighbours we didn't process yet // and score them to find out in which order to process - // push them to the stack in reverse order so we process the - // closest one first - for(unsigned int i = curr_nh_ind.size() - 1; i > 0; i--) { + for(unsigned int i = 0; i < curr_nh_ind.size(); i++) { unsigned int index = curr_nh_ind[i]; // score by how far away it is from the current point // and how parallel the normals are. double alignment = 1.0 - std::abs(glm::dot(pca[index].evec0, normal)); - double distance = glm::distance(pca[index].centroid, pca[curr].centroid); - double score = alignment; + double distance = glm::distance(pca[index].centroid, point) / rad; + double score = distance + alignment; if(!visited[index]) { scores[index].first = curr; scores[index].second = score; - stack.push_back(index); + queue.push_back(index); + std::push_heap(queue.begin(), queue.end(), cmp); visited[index] = true; } else if(scores[index].second > score) { // update current neighbors parent to current node, since it's closer scores[index].first = curr; scores[index].second = score; + // re-sort the heap with the new score + std::make_heap(queue.begin(), queue.end(), cmp); } } }; @@ -354,10 +363,12 @@ inline std::vector<std::pair<unsigned int, unsigned int>> CgPointWrangler::makeN visit(max_y_index); // start processing - while(!stack.empty()) { - unsigned int curr = stack.back(); + while(!queue.empty()) { + // pop the index with the smallest score + std::pop_heap(queue.begin(), queue.end(), cmp); + unsigned int curr = queue.back(); unsigned int parent = scores[curr].first; - stack.pop_back(); + queue.pop_back(); spanning_tree.push_back({parent, curr}); visit(curr); } @@ -400,7 +411,7 @@ inline std::vector<PCA> CgPointWrangler::performHierarchicalSimplification( float max_cluster_radius ){ unsigned int MAX_POINTS = std::min(100.0f, max_cluster_size); - unsigned int MIN_POINTS = 6; + unsigned int MIN_POINTS = 3; std::vector<unsigned int> hist; hist.resize(MAX_POINTS + 1, 0); @@ -431,6 +442,8 @@ inline std::vector<PCA> CgPointWrangler::performHierarchicalSimplification( } else { // split it & recurse // indices vector is not behind mutex because + // indices vector is not behind mutex because + // indices vector is not behind mutex because // the threads work on mutually exclusive ranges unsigned int lower = job.first; unsigned int upper = job.second; diff --git a/CgSceneGraph/CgSceneControl.cpp b/CgSceneGraph/CgSceneControl.cpp index 0f858ea0d188b10d32b39daf218fdbdc88ee5d78..4e94832f09e3264a936e1b37250dae401770474e 100644 --- a/CgSceneGraph/CgSceneControl.cpp +++ b/CgSceneGraph/CgSceneControl.cpp @@ -304,7 +304,7 @@ void CgSceneControl::handleEvent(CgBaseEvent* e) { std::vector<glm::vec3> new_colors(pca.size()); CgPointWrangler::buildKdTree(pca.data(), pca.data() + pca.size(), 0); for(unsigned int i = 0; i < pca.size(); i++) new_points[i] = pca[i].centroid; - std::vector<std::vector<unsigned int>> neighbourhoods = CgPointWrangler::getKNeighbourhoods(5, new_points); + std::vector<std::vector<unsigned int>> neighbourhoods = CgPointWrangler::getKNeighbourhoods(15, new_points); std::vector<std::pair<unsigned int, unsigned int>> spanning_tree = CgPointWrangler::makeNaiveSpanningTree(neighbourhoods, pca); std::vector<glm::vec3> new_normals = CgPointWrangler::alignNormals(glm::vec3(0.0,1.0,0.0), spanning_tree, pca);