diff --git a/CMakeLists.txt b/CMakeLists.txt index 7bc0f6fa..bff76e87 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,7 +8,7 @@ if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE Release) endif() -set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) add_compile_options(-Wall -Wextra -Wno-unused-result) diff --git a/include/gproshan/geometry/convex_hull.h b/include/gproshan/geometry/convex_hull.h index eb7291e4..a7e2abcb 100644 --- a/include/gproshan/geometry/convex_hull.h +++ b/include/gproshan/geometry/convex_hull.h @@ -20,13 +20,13 @@ class convex_hull std::vector CH; ///< convex hull points clockwise public: - convex_hull(const std::vector & points); - convex_hull(const vertex * points, const size_t & n_points); - operator const std::vector & (); + convex_hull(const std::vector & points, const real_t & precision = 1000); + convex_hull(const vertex * points, const size_t & n_points, const real_t & precision = 1000); + operator const std::vector & () const; private: - void andrew_algorithm(const vertex * points, const size_t & n_points); - bool ccw(const vertex & p, const vertex & q, const vertex & r); + void andrew_algorithm(const std::vector & points); + bool ccw(const ivec2 & p, const ivec2 & q, const ivec2 & r); }; diff --git a/include/gproshan/geometry/vec.h b/include/gproshan/geometry/vec.h index 922f742c..acf42820 100644 --- a/include/gproshan/geometry/vec.h +++ b/include/gproshan/geometry/vec.h @@ -274,6 +274,14 @@ vec operator / (const T & a, const vec & v) return res; } +///< cross product +template +__host_device__ +T cross(const vec & u, const vec & v) +{ + return u.x() * v.y() - v.x() * u.y(); +} + ///< cross product template __host_device__ diff --git a/include/gproshan/mdict/mdict.h b/include/gproshan/mdict/mdict.h index 78f2d1de..cd4648d8 100644 --- a/include/gproshan/mdict/mdict.h +++ b/include/gproshan/mdict/mdict.h @@ -20,7 +20,6 @@ struct locval_t real_t val; }; -bool operator < (const locval_t & a, const locval_t & b); void OMP(std::vector & alpha, const a_vec & x, const index_t & i, const a_mat & D, const size_t & L); diff --git a/src/gproshan/features/key_points.cpp b/src/gproshan/features/key_points.cpp index 38005fed..69c5de69 100644 --- a/src/gproshan/features/key_points.cpp +++ b/src/gproshan/features/key_points.cpp @@ -30,7 +30,7 @@ void key_points::compute_kps_areas(che * mesh, const real_t & percent) for(index_t f = 0; f < mesh->n_trigs; ++f) face_areas[f] = { mesh->area_trig(f), f }; - std::sort(begin(face_areas), end(face_areas)); + std::ranges::sort(face_areas); is_kp.assign(mesh->n_vertices, false); kps.reserve(mesh->n_vertices); diff --git a/src/gproshan/geometry/convex_hull.cpp b/src/gproshan/geometry/convex_hull.cpp index 37b9e9aa..d0dbbd4b 100644 --- a/src/gproshan/geometry/convex_hull.cpp +++ b/src/gproshan/geometry/convex_hull.cpp @@ -8,34 +8,41 @@ namespace gproshan { -convex_hull::convex_hull(const std::vector & points): convex_hull(points.data(), size(points)) {} +convex_hull::convex_hull(const std::vector & points, const real_t & precision): convex_hull(points.data(), size(points), precision) {} -convex_hull::convex_hull(const vertex * points, const size_t & n_points) +convex_hull::convex_hull(const vertex * points, const size_t & n_points, const real_t & precision) { - andrew_algorithm(points, n_points); + std::vector points2d(n_points); + + #pragma omp parallel for + for(index_t i = 0; i < n_points; ++i) + { + const vertex & p = points[i] * precision; + points2d[i] = {int(p.x()), int(p.y())}; + } + andrew_algorithm(points2d); } -convex_hull::operator const std::vector & () +convex_hull::operator const std::vector & () const { return CH; } ///< Andrew's Convex Hull Algorithm: Competitive Programming 4 -void convex_hull::andrew_algorithm(const vertex * points, const size_t & n_points) +void convex_hull::andrew_algorithm(const std::vector & points) { - std::vector idx(n_points); + std::vector idx(size(points)); std::iota(begin(idx), end(idx), 0); - std::sort(begin(idx), end(idx), - [&points](const index_t & i, const index_t & j) - { - return points[i] < points[j]; - }); + std::ranges::sort(idx, [&points](const index_t & i, const index_t & j) + { + return points[i] < points[j]; + }); - CH.resize(2 * n_points); + CH.resize(2 * size(points)); index_t k = 0; - for(index_t p = 0; p < n_points; ++p) + for(index_t p = 0; p < size(points); ++p) { const index_t & i = idx[p]; while(k > 1 && !ccw(points[CH[k - 2]], points[CH[k - 1]], points[i])) --k; @@ -43,7 +50,7 @@ void convex_hull::andrew_algorithm(const vertex * points, const size_t & n_point } index_t t = k; - for(index_t p = n_points - 2; p > 0; --p) + for(index_t p = size(points) - 2; p > 0; --p) { const index_t & i = idx[p]; while(k > t && !ccw(points[CH[k - 2]], points[CH[k - 1]], points[i])) --k; @@ -55,10 +62,9 @@ void convex_hull::andrew_algorithm(const vertex * points, const size_t & n_point CH.resize(k); } -bool convex_hull::ccw(const vertex & p, const vertex & q, const vertex & r) +bool convex_hull::ccw(const ivec2 & p, const ivec2 & q, const ivec2 & r) { - // TODO vec2 - return cross(q - p, r - p).z() > 0; + return cross(q - p, r - p) > 0; } diff --git a/src/gproshan/mdict/mdict.cpp b/src/gproshan/mdict/mdict.cpp index 39ff79a6..d377b25d 100644 --- a/src/gproshan/mdict/mdict.cpp +++ b/src/gproshan/mdict/mdict.cpp @@ -17,11 +17,6 @@ const real_t sigma = 0.01; // SPARSE -bool operator < (const locval_t & a, const locval_t & b) -{ - return (a.i == b.i) ? a.j < b.j : a.i < b.i; -} - std::ostream & operator << (std::ostream & os, const locval_t & lc) { return os << '(' << lc.i << ',' << lc.j << ") = " << lc.val; @@ -77,7 +72,10 @@ void sp_KSVD(a_mat & D, const a_mat & X, const size_t & L, size_t k) { a_sp_mat alpha = OMP_all(locval, X, D, L); - std::sort(locval.begin(), locval.end()); + std::ranges::sort(locval, [](const locval_t & a, const locval_t & b) + { + return a.i == b.i ? a.j < b.j : a.i < b.i; + }); rows.push_back(0); for(index_t k = 1; k < size(locval); ++k) @@ -360,7 +358,10 @@ void sp_KSVD(a_mat & A, const std::vector & patches, const size_t & L, si { a_sp_mat alpha = OMP_all(locval, patches, A, L); - std::sort(locval.begin(), locval.end()); + std::ranges::sort(locval, [](const locval_t & a, const locval_t & b) + { + return a.i == b.i ? a.j < b.j : a.i < b.i; + }); rows.push_back(0); for(index_t k = 1; k < size(locval); ++k) diff --git a/src/gproshan/mdict/msparse_coding.cpp b/src/gproshan/mdict/msparse_coding.cpp index fc3b85f6..09ca3209 100644 --- a/src/gproshan/mdict/msparse_coding.cpp +++ b/src/gproshan/mdict/msparse_coding.cpp @@ -891,7 +891,7 @@ real_t msparse_coding::mesh_reconstruction(const fmask_t & mask) rp.xyz.row(2) = x.t(); } - std::sort(patches_error.begin(), patches_error.end()); + std::ranges::sort(patches_error); fprintf(stderr, "error %16s%16s\n", "best", "worst"); for(index_t i = 0; i < 10; ++i) diff --git a/src/gproshan/mdict/patch.cpp b/src/gproshan/mdict/patch.cpp index cf6864a8..189a31f1 100644 --- a/src/gproshan/mdict/patch.cpp +++ b/src/gproshan/mdict/patch.cpp @@ -414,7 +414,7 @@ void patch::add_extra_xyz_disjoint(che * mesh, std::vector & vpatche vpatches_t & ma = vpatches[mesh->halfedge(he_next(he))]; vpatches_t & mb = vpatches[mesh->halfedge(he_prev(he))]; - if(ma.find(p) != ma.end() && mb.find(p) != mb.end()) + if(ma.contains(p) && mb.contains(p)) { arma::uvec xi = { vpatches[min_v][p], ma[p], mb[p] }; abc = xyz.cols(xi); @@ -600,7 +600,7 @@ void patch::jet_fit_directions(che * mesh, const index_t & v) My_Monge_form monge_form; My_Monge_via_jet_fitting monge_fit; - monge_form = monge_fit(in_points.begin(), in_points.end(), d_fitting, d_monge); + monge_form = monge_fit(begin(in_points), end(in_points), d_fitting, d_monge); vertex normal = mesh->normal(v); monge_form.comply_wrt_given_normal(DVector(normal.x(), normal.y(), normal.z())); @@ -736,9 +736,9 @@ void patch::compute_avg_distance(che * mesh, std::vector & vpatches, distances.push_back(norm(a - b)); } */ - std::sort(distances.begin(), distances.end()); + std::ranges::sort(distances); size_t n_elem = size(distances); - if(size(distances)%2 ==0) + if(size(distances) % 2 ==0) { avg_dist = (distances[n_elem/2] + distances[(n_elem/2 -1)])/2; } diff --git a/src/gproshan/mesh/che_fill_hole.cpp b/src/gproshan/mesh/che_fill_hole.cpp index 4d99018c..1fc5497d 100644 --- a/src/gproshan/mesh/che_fill_hole.cpp +++ b/src/gproshan/mesh/che_fill_hole.cpp @@ -118,7 +118,7 @@ che * mesh_fill_hole(che * mesh, const std::vector & border_vertices, c } else // fill rest partial holes { - reverse(merge_vertices[!c].begin(), merge_vertices[!c].end()); + reverse(begin(merge_vertices[!c]), end(merge_vertices[!c])); for(index_t v: merge_vertices[!c]) vertices[c].push_back(hole->point(v)); @@ -172,7 +172,7 @@ che * mesh_fill_hole(che * mesh, const std::vector & border_vertices, c } else { - reverse(merge_vertices[!c].begin(), merge_vertices[!c].end()); + reverse(begin(merge_vertices[!c]), end(merge_vertices[!c])); for(index_t v: merge_vertices[!c]) vertices[c].push_back(hole->point(v)); diff --git a/src/gproshan/pointcloud/knn.cpp b/src/gproshan/pointcloud/knn.cpp index 9c7986d9..6a35d8d9 100644 --- a/src/gproshan/pointcloud/knn.cpp +++ b/src/gproshan/pointcloud/knn.cpp @@ -49,7 +49,7 @@ std::vector grid::operator () (const point & p, int k) const continue; const auto & iter = voxels.find(pos); - if(iter == voxels.end()) + if(iter == end(voxels)) continue; for(const index_t & v: iter->second) diff --git a/src/gproshan/scenes/scene.cpp b/src/gproshan/scenes/scene.cpp index 31d5d54e..f64806a9 100644 --- a/src/gproshan/scenes/scene.cpp +++ b/src/gproshan/scenes/scene.cpp @@ -165,7 +165,7 @@ bool scene::load_mtl(const std::string & file) : materials.back().map_bump; sscanf(line, "%*s %s", str); if(str[0] == '-') continue; // ignoring map textures with options - if(texture_id.find(str) == texture_id.end()) + if(!texture_id.contains(str)) { texture_id[str] = size(texture_name); texture_name.push_back(str); diff --git a/src/gproshan/viewer/viewer.cpp b/src/gproshan/viewer/viewer.cpp index a6a66d5a..3d2f9211 100644 --- a/src/gproshan/viewer/viewer.cpp +++ b/src/gproshan/viewer/viewer.cpp @@ -452,7 +452,6 @@ void viewer::init_menus() add_menu("Viewer", { add_process("Help", m_help, GLFW_KEY_F1), - add_process("Close", m_close, GLFW_KEY_ESCAPE), add_process("Maximize", m_maximize, GLFW_KEY_F11), add_process("Hide/Show ImGui", m_hide_show_imgui, GLFW_KEY_I), add_process("Save/Load view", m_save_load_view, GLFW_KEY_PERIOD), @@ -461,29 +460,30 @@ void viewer::init_menus() add_process("Background color inc", m_bgc_inc, GLFW_KEY_RIGHT), add_process("Background color dec", m_bgc_dec, GLFW_KEY_LEFT), add_process("Background color white", m_bgc_white, GLFW_KEY_1), - add_process("Background color black", m_bgc_black, GLFW_KEY_0) + add_process("Background color black", m_bgc_black, GLFW_KEY_0), + add_process("Close", m_close, GLFW_KEY_ESCAPE) }); add_menu("Render", { + add_process("Render Flat", m_render_flat, GLFW_KEY_TAB), add_process("Render Point Cloud", m_render_pointcloud, GLFW_KEY_F5), add_process("Render Wireframe", m_render_wireframe, GLFW_KEY_F6), add_process("Render Triangles", m_render_triangles, GLFW_KEY_F7), add_process("Render GL", m_render_gl, GLFW_KEY_F8), - add_process("Level Curves", m_render_lines, GLFW_KEY_SPACE), - add_process("Render Flat", m_render_flat, GLFW_KEY_TAB), - add_process("Setup Raytracing", m_setup_raytracing, GLFW_KEY_R), add_process("Render Embree", m_render_embree, GLFW_KEY_F9), #ifdef GPROSHAN_OPTIX add_process("Render OptiX", m_render_optix, GLFW_KEY_F10), #endif // GPROSHAN_OPTIX - add_process("Raycasting", m_raycasting, GLFW_KEY_ENTER) + add_process("Setup Raytracing", m_setup_raytracing, GLFW_KEY_R), + add_process("Raycasting", m_raycasting, GLFW_KEY_ENTER), + add_process("Level Curves", m_render_lines, GLFW_KEY_SPACE) }); add_menu("Mesh", { - add_process("Reload/Reset", m_reset_mesh, GLFW_KEY_INSERT), add_process("Save Mesh", m_save_mesh, GLFW_KEY_W), + add_process("Reload/Reset", m_reset_mesh, GLFW_KEY_INSERT), add_process("Remove Selected Mesh", m_remove_mesh, GLFW_KEY_DELETE), add_process("Pop Mesh", m_pop_mesh, GLFW_KEY_BACKSPACE), add_process("Normalize Mesh", m_normalize_mesh), @@ -534,7 +534,7 @@ int viewer::add_process(const char * name, const function_t & f, const int & key static int nk = 1000; const int & fkey = key == -1 ? ++nk : key; - if(processes.find(fkey) != processes.end()) + if(processes.contains(fkey)) { fprintf(stderr, "repeated key: [%d] %s (%s)\n", key, glfw_key_name.at(key), name); return -1; @@ -674,7 +674,7 @@ void viewer::keyboard_callback(GLFWwindow * window, int key, int, int action, in if(action == GLFW_RELEASE) return; viewer * view = (viewer *) glfwGetWindowUserPointer(window); - if(view->processes.find(key) == view->processes.end()) + if(!view->processes.contains(key)) return; process_t & pro = view->processes[key];