From b5b708a6bad5ddf858e7f0d30fad61978e37bd4f Mon Sep 17 00:00:00 2001 From: Max Lyon Date: Fri, 27 Sep 2019 16:34:20 +0200 Subject: [PATCH] smart range improvements --- src/OpenMesh/Core/Mesh/SmartRange.hh | 82 +++++++++++++++++++++++++ src/Unittests/unittests_smart_ranges.cc | 64 ++++++++++++++++++- 2 files changed, 145 insertions(+), 1 deletion(-) diff --git a/src/OpenMesh/Core/Mesh/SmartRange.hh b/src/OpenMesh/Core/Mesh/SmartRange.hh index f6bac807..43ab02cd 100644 --- a/src/OpenMesh/Core/Mesh/SmartRange.hh +++ b/src/OpenMesh/Core/Mesh/SmartRange.hh @@ -43,6 +43,8 @@ #pragma once #include +#include +#include //== NAMESPACES =============================================================== @@ -52,12 +54,24 @@ namespace OpenMesh { //== CLASS DEFINITION ========================================================= +namespace { + +struct Identity +{ + template + T operator()(const T& _t) const { return _t; } +}; + +} + /// Base class for all smart range types template struct SmartRangeT { // TODO: Someone with better c++ knowledge may improve the code below. + + template auto sum(Functor&& f) -> decltype (f(std::declval())+f(std::declval())) { @@ -92,6 +106,74 @@ struct SmartRangeT return (1.0 / n_elements) * sum; } + template + auto to_array(Functor&& f = {}) -> std::array()))>::type, n> + { + auto range = static_cast(this); + std::array()))>::type, n> res; + auto it = range->begin(); + auto end = range->end(); + int i = 0; + while (i < n && it != end) + res[i++] = f(*(it++)); + return res; + } + + template + auto to_vector(Functor&& f = {}) -> std::vector()))>::type> + { + auto range = static_cast(this); + std::vector()))>::type> res; + for (auto e : *range) + res.push_back(f(e)); + return res; + } + + + template + auto elem_wise_min(Functor&& f) -> typename std::remove_reference()))>::type + { + auto range = static_cast(this); + auto it = range->begin(); + auto end = range->end(); + assert(it != end); + + typename std::remove_reference()))>::type min = f(*it); + ++it; + + for (; it != end; ++it) + { + const auto& tmp = f(*it); + for (int i = 0; i < n; ++i) + min[i] = std::min(min[i], tmp[i]); + } + + return min; + } + + template + auto elem_wise_max(Functor&& f) -> typename std::remove_reference()))>::type + { + auto range = static_cast(this); + auto it = range->begin(); + auto end = range->end(); + assert(it != end); + + typename std::remove_reference()))>::type max = f(*it); + ++it; + + for (; it != end; ++it) + { + const auto& tmp = f(*it); + for (int i = 0; i < n; ++i) + max[i] = std::max(max[i], tmp[i]); + } + + return max; + } + + + }; diff --git a/src/Unittests/unittests_smart_ranges.cc b/src/Unittests/unittests_smart_ranges.cc index 15b7da3f..892c0c73 100644 --- a/src/Unittests/unittests_smart_ranges.cc +++ b/src/Unittests/unittests_smart_ranges.cc @@ -198,7 +198,6 @@ TEST_F(OpenMeshSmartRanges, Sum) TEST_F(OpenMeshSmartRanges, PropertyManagerAsFunctor) { auto myPos = OpenMesh::makeTemporaryProperty(mesh_); - for (auto vh : mesh_.vertices()) myPos(vh) = mesh_.point(vh); @@ -212,6 +211,69 @@ TEST_F(OpenMeshSmartRanges, PropertyManagerAsFunctor) EXPECT_LT(norm(cog - cog2), 0.00001) << "Computed center of gravities are significantly different."; } +/* Test to vector + */ +TEST_F(OpenMeshSmartRanges, ToVector) +{ + auto uvs = OpenMesh::makeTemporaryProperty(mesh_); + + for (auto heh : mesh_.halfedges()) + uvs(heh) = OpenMesh::Vec2d(heh.idx(), (heh.idx() * 13)%7); + + for (auto fh : mesh_.faces()) + { + auto tri_uvs = fh.halfedges().to_vector(uvs); + auto heh_handles = fh.halfedges().to_vector(); +// for (auto heh : heh_handles) +// auto n = heh.next(); + } + + auto vertex_vec = mesh_.vertices().to_vector(); + for (auto vh : vertex_vec) + auto heh = vh.out(); +} + +/* Test to array + */ +TEST_F(OpenMeshSmartRanges, ToArray) +{ + auto uvs = OpenMesh::makeTemporaryProperty(mesh_); + + for (auto heh : mesh_.halfedges()) + uvs(heh) = OpenMesh::Vec2d(heh.idx(), (heh.idx() * 13)%7); + + for (auto fh : mesh_.faces()) + { + auto tri_uvs = fh.halfedges().to_array<3>(uvs); + auto heh_handles = fh.halfedges().to_array<3>(); + } +} + +/* Test bounding box + */ +TEST_F(OpenMeshSmartRanges, BoundingBox) +{ + auto myPos = OpenMesh::makeTemporaryProperty(mesh_); + for (auto vh : mesh_.vertices()) + myPos(vh) = mesh_.point(vh); + + auto uvs = OpenMesh::makeTemporaryProperty(mesh_); + for (auto heh : mesh_.halfedges()) + uvs(heh) = OpenMesh::Vec2d(heh.idx(), (heh.idx() * 13)%7); + + auto bb_min = mesh_.vertices().elem_wise_min<3>(myPos); + auto bb_max = mesh_.vertices().elem_wise_max<3>(myPos); + + EXPECT_LT(norm(bb_min - Mesh::Point(-1,-1,-1)), 0.000001) << "Bounding box minimum seems off"; + EXPECT_LT(norm(bb_max - Mesh::Point( 1, 1, 1)), 0.000001) << "Bounding box maximum seems off"; + + for (auto fh : mesh_.faces()) + { + auto uv_bb_min = fh.halfedges().elem_wise_min<2>(uvs); + auto uv_bb_max = fh.halfedges().elem_wise_max<2>(uvs); + } +} + }