Commit b5b708a6 authored by Max Lyon's avatar Max Lyon
Browse files

smart range improvements

parent f71696f2
......@@ -43,6 +43,8 @@
#pragma once
#include <utility>
#include <array>
#include <vector>
//== NAMESPACES ===============================================================
......@@ -52,12 +54,24 @@ namespace OpenMesh {
//== CLASS DEFINITION =========================================================
namespace {
struct Identity
{
template <typename T>
T operator()(const T& _t) const { return _t; }
};
}
/// Base class for all smart range types
template <typename RangeT, typename HandleT>
struct SmartRangeT
{
// TODO: Someone with better c++ knowledge may improve the code below.
template <typename Functor>
auto sum(Functor&& f) -> decltype (f(std::declval<HandleT>())+f(std::declval<HandleT>()))
{
......@@ -92,6 +106,74 @@ struct SmartRangeT
return (1.0 / n_elements) * sum;
}
template <int n, typename Functor = Identity>
auto to_array(Functor&& f = {}) -> std::array<typename std::remove_reference<decltype (f(std::declval<HandleT>()))>::type, n>
{
auto range = static_cast<const RangeT*>(this);
std::array<typename std::remove_reference<decltype (f(std::declval<HandleT>()))>::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 <typename Functor = Identity>
auto to_vector(Functor&& f = {}) -> std::vector<typename std::remove_reference<decltype (f(std::declval<HandleT>()))>::type>
{
auto range = static_cast<const RangeT*>(this);
std::vector<typename std::remove_reference<decltype (f(std::declval<HandleT>()))>::type> res;
for (auto e : *range)
res.push_back(f(e));
return res;
}
template <int n, typename Functor>
auto elem_wise_min(Functor&& f) -> typename std::remove_reference<decltype (f(std::declval<HandleT>()))>::type
{
auto range = static_cast<const RangeT*>(this);
auto it = range->begin();
auto end = range->end();
assert(it != end);
typename std::remove_reference<decltype (f(std::declval<HandleT>()))>::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 <int n, typename Functor>
auto elem_wise_max(Functor&& f) -> typename std::remove_reference<decltype (f(std::declval<HandleT>()))>::type
{
auto range = static_cast<const RangeT*>(this);
auto it = range->begin();
auto end = range->end();
assert(it != end);
typename std::remove_reference<decltype (f(std::declval<HandleT>()))>::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;
}
};
......
......@@ -198,7 +198,6 @@ TEST_F(OpenMeshSmartRanges, Sum)
TEST_F(OpenMeshSmartRanges, PropertyManagerAsFunctor)
{
auto myPos = OpenMesh::makeTemporaryProperty<OpenMesh::VertexHandle, Mesh::Point>(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<OpenMesh::HalfedgeHandle, OpenMesh::Vec2d>(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<OpenMesh::HalfedgeHandle, OpenMesh::Vec2d>(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<OpenMesh::VertexHandle, Mesh::Point>(mesh_);
for (auto vh : mesh_.vertices())
myPos(vh) = mesh_.point(vh);
auto uvs = OpenMesh::makeTemporaryProperty<OpenMesh::HalfedgeHandle, OpenMesh::Vec2d>(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);
}
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment