Commit 3a4da622 authored by Philip Trettner's avatar Philip Trettner
Browse files

cursor access for possibly-null pointers-to-attributes

parent 693d0664
......@@ -40,8 +40,18 @@ struct primitive_index
/// indexes this primitive by a functor
/// also works for attributes
/// - e.g. v[position] or f[area]
template <class FuncT>
auto operator[](FuncT&& f) const -> tmp::result_type_of<FuncT, index_t>;
template <class FuncT, class ResultT = tmp::result_type_of<FuncT, index_t>>
ResultT operator[](FuncT&& f) const;
/// indexes this primitive by an attribute pointer
/// if attr is null, returns writeable dummy location
/// CAUTION: always returns same writeable dummy location, this is intended as a write-only value!
template <class AttrT>
AttrT& operator[](attribute<AttrT>* attr) const;
/// indexes this primitive by an attribute pointer
/// if attr is null, returns default constructed value
template <class AttrT>
AttrT const& operator[](attribute<AttrT> const* attr) const;
};
template <class tag>
......@@ -69,8 +79,17 @@ struct primitive_handle
/// indexes this primitive by a functor
/// also works for attributes
/// - e.g. v[position] or f[area]
template <class FuncT>
auto operator[](FuncT&& f) const -> tmp::result_type_of<FuncT, handle_t>;
template <class FuncT, class ResultT = tmp::result_type_of<FuncT, index_t>>
ResultT operator[](FuncT&& f) const;
/// indexes this primitive by an attribute pointer
/// if attr is null, returns writeable dummy location
template <class AttrT>
AttrT& operator[](attribute<AttrT>* attr) const;
/// indexes this primitive by an attribute pointer
/// if attr is null, returns default constructed value
template <class AttrT>
AttrT const& operator[](attribute<AttrT> const* attr) const;
bool is_valid() const { return idx.is_valid(); } ///< valid idx (but could be deleted in some iterators)
bool is_invalid() const { return !idx.is_valid(); } ///< invalid idx
......
......@@ -5,19 +5,51 @@
namespace polymesh
{
template <class tag>
template <class FuncT>
auto primitive_index<tag>::operator[](FuncT&& f) const -> tmp::result_type_of<FuncT, index_t>
template <class FuncT, class ResultT>
ResultT primitive_index<tag>::operator[](FuncT&& f) const
{
return f(*static_cast<typename primitive<tag>::index const*>(this));
}
template <class tag>
template <class FuncT>
auto primitive_handle<tag>::operator[](FuncT&& f) const -> tmp::result_type_of<FuncT, handle_t>
template <class FuncT, class ResultT>
ResultT primitive_handle<tag>::operator[](FuncT&& f) const
{
return f(*static_cast<typename primitive<tag>::handle const*>(this));
}
template <class tag>
template <class AttrT>
AttrT& primitive_index<tag>::operator[](attribute<AttrT>* attr) const
{
static AttrT def_attr;
return attr ? (*attr)[*static_cast<typename primitive<tag>::handle const*>(this)] : def_attr;
}
template <class tag>
template <class AttrT>
AttrT const& primitive_index<tag>::operator[](attribute<AttrT> const* attr) const
{
static AttrT const def_attr;
return attr ? (*attr)[*static_cast<typename primitive<tag>::handle const*>(this)] : def_attr;
}
template <class tag>
template <class AttrT>
AttrT& primitive_handle<tag>::operator[](attribute<AttrT>* attr) const
{
static AttrT def_attr;
return attr ? (*attr)[*static_cast<typename primitive<tag>::handle const*>(this)] : def_attr;
}
template <class tag>
template <class AttrT>
AttrT const& primitive_handle<tag>::operator[](attribute<AttrT> const* attr) const
{
static AttrT const def_attr;
return attr ? (*attr)[*static_cast<typename primitive<tag>::handle const*>(this)] : def_attr;
}
inline bool vertex_handle::is_removed() const { return idx.is_valid() && low_level_api(mesh).is_removed(idx); }
inline bool face_handle::is_removed() const { return idx.is_valid() && low_level_api(mesh).is_removed(idx); }
inline bool edge_handle::is_removed() const { return idx.is_valid() && low_level_api(mesh).is_removed(idx); }
......@@ -75,7 +107,10 @@ inline edge_handle vertex_handle::any_edge() const
return mesh->handle_of(h.is_valid() ? low_level_api(mesh).edge_of(h) : edge_index::invalid());
}
inline vertex_handle face_handle::any_vertex() const { return mesh->handle_of(low_level_api(mesh).to_vertex_of(low_level_api(mesh).halfedge_of(idx))); }
inline vertex_handle face_handle::any_vertex() const
{
return mesh->handle_of(low_level_api(mesh).to_vertex_of(low_level_api(mesh).halfedge_of(idx)));
}
inline halfedge_handle face_handle::any_halfedge() const { return mesh->handle_of(low_level_api(mesh).halfedge_of(idx)); }
......
......@@ -287,13 +287,13 @@ auto smart_range<this_t, ElementT>::geometric_mean(FuncT &&f) const -> tmp::deca
template <class this_t, class ElementT>
template <class FuncT>
auto smart_range<this_t, ElementT>::aabb(FuncT &&f) const -> polymesh::aabb<typename tmp::decayed_result_of<FuncT, ElementT>::type>
auto smart_range<this_t, ElementT>::aabb(FuncT &&f) const -> polymesh::aabb<tmp::decayed_result_type_of<FuncT, ElementT>>
{
auto it_begin = static_cast<this_t const *>(this)->begin();
auto it_end = static_cast<this_t const *>(this)->end();
assert(it_begin != it_end && "requires non-empty range");
auto v = f(*it_begin);
polymesh::aabb<typename tmp::decayed_result_of<FuncT, ElementT>::type> r = {v, v};
polymesh::aabb<tmp::decayed_result_type_of<FuncT, ElementT>> r = {v, v};
++it_begin;
while (it_begin != it_end)
{
......@@ -307,7 +307,7 @@ auto smart_range<this_t, ElementT>::aabb(FuncT &&f) const -> polymesh::aabb<type
template <class this_t, class ElementT>
template <class FuncT>
auto smart_range<this_t, ElementT>::minmax(FuncT &&f) const -> polymesh::aabb<typename tmp::decayed_result_of<FuncT, ElementT>::type>
auto smart_range<this_t, ElementT>::minmax(FuncT &&f) const -> polymesh::aabb<tmp::decayed_result_type_of<FuncT, ElementT>>
{
return aabb(f);
}
......@@ -428,7 +428,7 @@ int smart_collection<mesh_ptr, tag, iterator>::size() const
template <class mesh_ptr, class tag, class iterator>
void smart_collection<mesh_ptr, tag, iterator>::reserve(int capacity) const
{
return typename primitive<tag>::reserve(*mesh, capacity);
return primitive<tag>::reserve(*mesh, capacity);
}
template <class mesh_ptr, class tag, class iterator>
......
......@@ -8,23 +8,25 @@ namespace polymesh
// small template metaprogramming
namespace tmp
{
template <class FuncT, class ArgT>
template <class FuncT>
struct decayed_result_of
{
template <class ArgT>
using type = typename std::decay<decltype(std::declval<FuncT>()(std::declval<ArgT>()))>::type;
};
template <class FuncT, class ArgT>
using decayed_result_type_of = typename decayed_result_of<FuncT, ArgT>::type;
using decayed_result_type_of = typename decayed_result_of<FuncT>::template type<ArgT>;
template <class FuncT, class ArgT>
template <class FuncT>
struct result_of
{
template <class ArgT>
using type = decltype(std::declval<FuncT>()(std::declval<ArgT>()));
};
template <class FuncT, class ArgT>
using result_type_of = typename result_of<FuncT, ArgT>::type;
using result_type_of = typename result_of<FuncT>::template type<ArgT>;
template <class T>
using enable_if_const_t = typename std::enable_if<std::is_const<T>::value, std::nullptr_t>::type;
......
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