Uniformize code style & do a few code rearrangements

This commit is contained in:
Nikita Lisitsa 2020-08-27 16:49:46 +03:00
parent a2b1d90c48
commit 6225f89f88
69 changed files with 460 additions and 481 deletions

View file

@ -1,6 +1,6 @@
file(GLOB_RECURSE PSEMEK_CG_HEADERS "include/*.hpp") file(GLOB_RECURSE PSEMEK_CG_HEADERS "include/*.hpp")
add_library(cg STATIC ${PSEMEK_CG_HEADERS}) add_library(cg ${PSEMEK_CG_HEADERS})
target_include_directories(cg PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include") target_include_directories(cg PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include")
target_link_libraries(cg PUBLIC geom) target_link_libraries(cg PUBLIC geom util)
set_target_properties(cg PROPERTIES LINKER_LANGUAGE CXX) set_target_properties(cg PROPERTIES LINKER_LANGUAGE CXX)

View file

@ -2,15 +2,15 @@
#include <psemek/geom/box.hpp> #include <psemek/geom/box.hpp>
namespace cg namespace psemek::cg
{ {
template <typename Iterator> template <typename Iterator>
auto bbox (Iterator begin, Iterator end) auto bbox(Iterator begin, Iterator end)
{ {
using point_type = std::decay_t<decltype(*begin)>; using point_type = std::decay_t<decltype(*begin)>;
box<typename point_type::scalar_type, point_type::dimension> result; geom::box<typename point_type::scalar_type, point_type::dimension> result;
for (; begin != end; ++begin) for (; begin != end; ++begin)
result |= *begin; result |= *begin;
return result; return result;

View file

@ -1,15 +1,15 @@
#pragma once #pragma once
#include <psemek/cg/dcel.hpp>
#include <psemek/geom/vector.hpp> #include <psemek/geom/vector.hpp>
#include <psemek/geom/point.hpp> #include <psemek/geom/point.hpp>
#include <psemek/cg/dcel.hpp>
namespace cg namespace psemek::cg
{ {
// TODO: this was written for Voronoi and is known to fail in some cases // TODO: this was written for Voronoi and is known to fail in some cases
template <typename T, typename Edge, typename Face, typename Index> template <typename T, typename Edge, typename Face, typename Index>
void clip (dcel<point<T, 2>, Edge, Face, Index> & dcel, cg::vector<T, 3> const & eq) void clip(dcel<geom::point<T, 2>, Edge, Face, Index> & dcel, geom::vector<T, 3> const & eq)
{ {
auto outer_face = dcel.face(0); auto outer_face = dcel.face(0);

View file

@ -6,11 +6,11 @@
#include <numeric> #include <numeric>
#include <vector> #include <vector>
namespace cg namespace psemek::cg
{ {
template <typename InIterator, typename OutIterator> template <typename InIterator, typename OutIterator>
OutIterator andrew_convex_hull (InIterator begin, InIterator end, OutIterator out) OutIterator andrew_convex_hull(InIterator begin, InIterator end, OutIterator out)
{ {
// need to store iterators to sort them // need to store iterators to sort them
std::vector<InIterator> its(end - begin); std::vector<InIterator> its(end - begin);
@ -25,7 +25,7 @@ namespace cg
// find lower half of the hull // find lower half of the hull
for (auto it = its.begin() + 1; it != its.end(); ++it) for (auto it = its.begin() + 1; it != its.end(); ++it)
{ {
while (hull.size() >= 2 && orientation(**(hull.end() - 2), **(hull.end() - 1), **it) != sign_t::positive) while (hull.size() >= 2 && orientation(**(hull.end() - 2), **(hull.end() - 1), **it) != geom::sign_t::positive)
hull.pop_back(); hull.pop_back();
hull.push_back(*it); hull.push_back(*it);
@ -37,7 +37,7 @@ namespace cg
if (*it == *(hull.end() - 2)) if (*it == *(hull.end() - 2))
continue; continue;
while (hull.size() >= 2 && orientation(**(hull.end() - 2), **(hull.end() - 1), **it) != sign_t::positive) while (hull.size() >= 2 && orientation(**(hull.end() - 2), **(hull.end() - 1), **it) != geom::sign_t::positive)
hull.pop_back(); hull.pop_back();
hull.push_back(*it); hull.push_back(*it);

View file

@ -6,11 +6,11 @@
#include <numeric> #include <numeric>
#include <vector> #include <vector>
namespace cg namespace psemek::cg
{ {
template <typename InIterator, typename OutIterator> template <typename InIterator, typename OutIterator>
OutIterator graham_convex_hull (InIterator begin, InIterator end, OutIterator out) OutIterator graham_convex_hull(InIterator begin, InIterator end, OutIterator out)
{ {
// need to store iterators to sort them // need to store iterators to sort them
std::vector<InIterator> its(end - begin); std::vector<InIterator> its(end - begin);
@ -27,9 +27,9 @@ namespace cg
auto o = orientation(*its.front(), *i1, *i2); auto o = orientation(*its.front(), *i1, *i2);
// carefully deal with parallel points // carefully deal with parallel points
if (o == sign_t::positive) if (o == geom::sign_t::positive)
return true; return true;
else if (o == sign_t::negative) else if (o == geom::sign_t::negative)
return false; return false;
return *i1 < *i2; return *i1 < *i2;
@ -41,7 +41,7 @@ namespace cg
for (auto it = its.begin() + 1; it != its.end(); ++it) for (auto it = its.begin() + 1; it != its.end(); ++it)
{ {
while (hull_end - its.begin() >= 2 && orientation(**(hull_end - 2), **(hull_end - 1), **it) != sign_t::positive) while (hull_end - its.begin() >= 2 && orientation(**(hull_end - 2), **(hull_end - 1), **it) != geom::sign_t::positive)
--hull_end; --hull_end;
*hull_end++ = *it; *hull_end++ = *it;

View file

@ -2,11 +2,11 @@
#include <psemek/geom/orientation.hpp> #include <psemek/geom/orientation.hpp>
namespace cg namespace psemek::cg
{ {
template <typename InIterator, typename OutIterator> template <typename InIterator, typename OutIterator>
OutIterator jarvis_convex_hull (InIterator begin, InIterator end, OutIterator out) OutIterator jarvis_convex_hull(InIterator begin, InIterator end, OutIterator out)
{ {
auto first_hull_point = std::min_element(begin, end); auto first_hull_point = std::min_element(begin, end);
auto last_hull_point = first_hull_point; auto last_hull_point = first_hull_point;
@ -26,7 +26,7 @@ namespace cg
if (jt == it) continue; if (jt == it) continue;
if (jt == last_hull_point) continue; if (jt == last_hull_point) continue;
if (orientation(*last_hull_point, *it, *jt) != cg::sign_t::positive) if (orientation(*last_hull_point, *it, *jt) != geom::sign_t::positive)
{ {
is_hull_edge = false; is_hull_edge = false;
break; break;

View file

@ -6,14 +6,14 @@
#include <numeric> #include <numeric>
#include <vector> #include <vector>
namespace cg namespace psemek::cg
{ {
namespace detail namespace detail
{ {
template <typename InIterator, typename ItIterator, typename OutIterator> template <typename InIterator, typename ItIterator, typename OutIterator>
OutIterator quick_hull_recursive_helper (InIterator p1, InIterator p2, ItIterator begin, ItIterator end, OutIterator out) OutIterator quick_hull_recursive_helper(InIterator p1, InIterator p2, ItIterator begin, ItIterator end, OutIterator out)
{ {
if (begin == end) if (begin == end)
return *out++ = p1; return *out++ = p1;
@ -21,11 +21,11 @@ namespace cg
// find point in [begin, end) furthest from segment (p1,p2) // find point in [begin, end) furthest from segment (p1,p2)
auto mid = *std::max_element(begin, end, [&](auto it1, auto it2){ auto mid = *std::max_element(begin, end, [&](auto it1, auto it2){
// TODO: design a robust predicate // TODO: design a robust predicate
return orientation(*it2, (*it2) + ((*p2) - (*p1)), *it1) == sign_t::positive; return orientation(*it2, (*it2) + ((*p2) - (*p1)), *it1) == geom::sign_t::positive;
}); });
auto end1 = std::partition(begin, end, [&](auto it){ return orientation(*p1, *it, *mid) == sign_t::positive; }); auto end1 = std::partition(begin, end, [&](auto it){ return orientation(*p1, *it, *mid) == geom::sign_t::positive; });
auto end2 = std::partition(end1, end, [&](auto it){ return orientation(*mid, *it, *p2) == sign_t::positive; }); auto end2 = std::partition(end1, end, [&](auto it){ return orientation(*mid, *it, *p2) == geom::sign_t::positive; });
out = quick_hull_recursive_helper(p1, mid, begin, end1, out); out = quick_hull_recursive_helper(p1, mid, begin, end1, out);
out = quick_hull_recursive_helper(mid, p2, end1, end2, out); out = quick_hull_recursive_helper(mid, p2, end1, end2, out);
@ -36,7 +36,7 @@ namespace cg
} }
template <typename InIterator, typename OutIterator> template <typename InIterator, typename OutIterator>
OutIterator quick_hull (InIterator begin, InIterator end, OutIterator out) OutIterator quick_hull(InIterator begin, InIterator end, OutIterator out)
{ {
// need to store iterators to move sets of points around // need to store iterators to move sets of points around
std::vector<InIterator> its(end - begin); std::vector<InIterator> its(end - begin);
@ -52,7 +52,7 @@ namespace cg
{ {
auto p = std::find_if(its.begin() + 1, its.end(), [&](auto it){ auto p = std::find_if(its.begin() + 1, its.end(), [&](auto it){
return std::all_of(its.begin() + 1, its.end(), [&](auto jt){ return std::all_of(its.begin() + 1, its.end(), [&](auto jt){
return it == jt || orientation(*its.front(), *it, *jt) == sign_t::negative; return it == jt || orientation(*its.front(), *it, *jt) == geom::sign_t::negative;
}); });
}); });
std::iter_swap(its.begin() + 1, p); std::iter_swap(its.begin() + 1, p);

View file

@ -1,12 +1,13 @@
#pragma once #pragma once
#include <psemek/cg/utility.hpp> #include <psemek/util/empty.hpp>
#include <psemek/util/ebo.hpp>
#include <cstddef> #include <cstddef>
#include <vector> #include <vector>
#include <cassert> #include <cassert>
namespace cg namespace psemek::cg
{ {
namespace detail namespace detail
@ -36,21 +37,21 @@ namespace cg
template <typename DCEL, typename Index, typename Tag> template <typename DCEL, typename Index, typename Tag>
struct handle_base struct handle_base
{ {
handle_base ( ) handle_base()
: owner_(nullptr) : owner_(nullptr)
, i_(static_cast<Index>(-1)) , i_(static_cast<Index>(-1))
{ } {}
handle_base (DCEL * owner, Index i) handle_base(DCEL * owner, Index i)
: owner_(owner) : owner_(owner)
, i_(i) , i_(i)
{ } {}
DCEL & owner ( ) const { return *owner_; } DCEL & owner() const { return *owner_; }
Index index ( ) const { return i_; } Index index() const { return i_; }
explicit operator bool ( ) const { return i_ != static_cast<Index>(-1); } explicit operator bool() const { return i_ != static_cast<Index>(-1); }
friend bool operator == (handle_base const & h1, handle_base const & h2) friend bool operator == (handle_base const & h1, handle_base const & h2)
{ {
@ -87,9 +88,9 @@ namespace cg
Index i_; Index i_;
}; };
struct point_tag { }; struct point_tag{};
struct edge_tag { }; struct edge_tag{};
struct face_tag { }; struct face_tag{};
} }
@ -118,14 +119,14 @@ namespace cg
{ {
using detail::handle_base<dcel, Index, detail::point_tag>::handle_base; using detail::handle_base<dcel, Index, detail::point_tag>::handle_base;
Point & data ( ) const; Point & data() const;
edge_handle edge ( ) const; edge_handle edge() const;
void edge (edge_handle h); void edge(edge_handle h);
protected: protected:
point_rec & get ( ) const point_rec & get() const
{ {
assert(this->owner_ != nullptr); assert(this->owner_ != nullptr);
assert(this->i_ < this->owner_->points.size()); assert(this->i_ < this->owner_->points.size());
@ -137,20 +138,20 @@ namespace cg
{ {
using detail::handle_base<dcel, Index, detail::edge_tag>::handle_base; using detail::handle_base<dcel, Index, detail::edge_tag>::handle_base;
Edge & data ( ) const; Edge & data() const;
point_handle origin ( ) const; point_handle origin() const;
edge_handle next ( ) const; edge_handle next() const;
edge_handle twin ( ) const; edge_handle twin() const;
face_handle face ( ) const; face_handle face() const;
void origin (point_handle h); void origin(point_handle h);
void next (edge_handle h); void next(edge_handle h);
void twin (edge_handle h); void twin(edge_handle h);
void face (face_handle h); void face(face_handle h);
protected: protected:
edge_rec & get ( ) const edge_rec & get() const
{ {
assert(this->owner_ != nullptr); assert(this->owner_ != nullptr);
assert(this->i_ < this->owner_->edges.size()); assert(this->i_ < this->owner_->edges.size());
@ -162,14 +163,14 @@ namespace cg
{ {
using detail::handle_base<dcel, Index, detail::face_tag>::handle_base; using detail::handle_base<dcel, Index, detail::face_tag>::handle_base;
Face & data ( ) const; Face & data() const;
edge_handle edge ( ) const; edge_handle edge() const;
void edge (edge_handle h); void edge(edge_handle h);
protected: protected:
face_rec & get ( ) const face_rec & get() const
{ {
assert(this->owner_ != nullptr); assert(this->owner_ != nullptr);
assert(this->i_ < this->owner_->faces.size()); assert(this->i_ < this->owner_->faces.size());
@ -177,43 +178,43 @@ namespace cg
} }
}; };
point_handle point (Index i) point_handle point(Index i)
{ {
return {this, i}; return {this, i};
} }
edge_handle edge (Index i) edge_handle edge(Index i)
{ {
return {this, i}; return {this, i};
} }
face_handle face (Index i) face_handle face(Index i)
{ {
return {this, i}; return {this, i};
} }
point_handle push_point (Point data = {}) point_handle push_point(Point data = {})
{ {
auto i = static_cast<Index>(points.size()); auto i = static_cast<Index>(points.size());
points.push_back({{std::move(data)}, null}); points.push_back({{std::move(data)}, null});
return point(i); return point(i);
} }
edge_handle push_edge (Edge data = {}) edge_handle push_edge(Edge data = {})
{ {
auto i = static_cast<Index>(edges.size()); auto i = static_cast<Index>(edges.size());
edges.push_back({{std::move(data)}, null, null, null, null}); edges.push_back({{std::move(data)}, null, null, null, null});
return edge(i); return edge(i);
} }
face_handle push_face (Face data = {}) face_handle push_face(Face data = {})
{ {
auto i = static_cast<Index>(faces.size()); auto i = static_cast<Index>(faces.size());
faces.push_back({{std::move(data)}, null}); faces.push_back({{std::move(data)}, null});
return face(i); return face(i);
} }
point_handle insert_point (Index i, Point data = {}) point_handle insert_point(Index i, Point data = {})
{ {
points.insert(points.begin() + i, {{std::move(data)}, null}); points.insert(points.begin() + i, {{std::move(data)}, null});
for (auto & e : edges) for (auto & e : edges)
@ -224,7 +225,7 @@ namespace cg
return point(i); return point(i);
} }
edge_handle insert_edge (Index i, Edge data = {}) edge_handle insert_edge(Index i, Edge data = {})
{ {
edges.insert(edges.begin() + i, {{std::move(data)}, null, null, null, null}); edges.insert(edges.begin() + i, {{std::move(data)}, null, null, null, null});
for (auto & p : points) for (auto & p : points)
@ -247,7 +248,7 @@ namespace cg
return edge(i); return edge(i);
} }
face_handle insert_face (Index i, Face data = {}) face_handle insert_face(Index i, Face data = {})
{ {
faces.insert(faces.begin() + i, {{std::move(data)}, null}); faces.insert(faces.begin() + i, {{std::move(data)}, null});
for (auto & e : edges) for (auto & e : edges)
@ -258,7 +259,7 @@ namespace cg
return face(i); return face(i);
} }
void remove_point (point_handle h) void remove_point(point_handle h)
{ {
points.erase(points.begin() + h.index()); points.erase(points.begin() + h.index());
for (auto & e : edges) for (auto & e : edges)
@ -268,7 +269,7 @@ namespace cg
} }
} }
void remove_edge (edge_handle h) void remove_edge(edge_handle h)
{ {
edges.erase(edges.begin() + h.index()); edges.erase(edges.begin() + h.index());
for (auto & p : points) for (auto & p : points)
@ -290,7 +291,7 @@ namespace cg
} }
} }
void remove_face (face_handle h) void remove_face(face_handle h)
{ {
faces.erase(faces.begin() + h.index()); faces.erase(faces.begin() + h.index());
for (auto & e : edges) for (auto & e : edges)
@ -435,7 +436,7 @@ namespace cg
} }
template <typename Index = std::size_t, typename Iterator> template <typename Index = std::size_t, typename Iterator>
auto polygon_dcel (Iterator begin, Iterator end) auto polygon_dcel(Iterator begin, Iterator end)
{ {
using point_type = std::decay_t<decltype(*begin)>; using point_type = std::decay_t<decltype(*begin)>;

View file

@ -2,11 +2,11 @@
#include <psemek/cg/dcel.hpp> #include <psemek/cg/dcel.hpp>
namespace cg namespace psemek::cg
{ {
template <typename Point, typename Edge, typename Face, typename Index> template <typename Point, typename Edge, typename Face, typename Index>
dcel<Face, Edge, Point, Index> dual (dcel<Point, Edge, Face, Index> const & d) dcel<Face, Edge, Point, Index> dual(dcel<Point, Edge, Face, Index> const & d)
{ {
dcel<Face, Edge, Point, Index> result; dcel<Face, Edge, Point, Index> result;

View file

@ -1,7 +1,6 @@
#pragma once #pragma once
#include <psemek/geom/intersection.hpp> #include <psemek/geom/intersection.hpp>
#include <psemek/cg/utility.hpp>
#include <cstddef> #include <cstddef>
#include <algorithm> #include <algorithm>
@ -11,11 +10,11 @@
#include <deque> #include <deque>
#include <set> #include <set>
namespace cg namespace psemek::cg
{ {
template <typename InIterator, typename OutIterator> template <typename InIterator, typename OutIterator>
OutIterator segment_intersection (InIterator begin, InIterator end, OutIterator out) OutIterator segment_intersection(InIterator begin, InIterator end, OutIterator out)
{ {
using segment = std::decay_t<decltype(*begin)>; using segment = std::decay_t<decltype(*begin)>;
using point = typename segment::point_type; using point = typename segment::point_type;
@ -39,7 +38,7 @@ namespace cg
struct event_comparator struct event_comparator
{ {
bool operator() (event const & e1, event const & e2) const bool operator()(event const & e1, event const & e2) const
{ {
return e1.p > e2.p; return e1.p > e2.p;
} }
@ -71,7 +70,7 @@ namespace cg
{ {
scalar & sweep_line; scalar & sweep_line;
bool operator() (InIterator it1, InIterator it2) const bool operator()(InIterator it1, InIterator it2) const
{ {
scalar const eps = 1e-4; scalar const eps = 1e-4;
scalar const y1 = (*it1)[0][1] + ((*it1)[1][1] -(*it1)[0][1]) * (sweep_line + eps - (*it1)[0][0]) / ((*it1)[1][0] - (*it1)[0][0]); scalar const y1 = (*it1)[0][1] + ((*it1)[1][1] -(*it1)[0][1]) * (sweep_line + eps - (*it1)[0][0]) / ((*it1)[1][0] - (*it1)[0][0]);

View file

@ -5,11 +5,11 @@
#include <queue> #include <queue>
namespace cg namespace psemek::cg
{ {
template <typename Index = std::size_t, typename InputIterator> template <typename Index = std::size_t, typename InputIterator>
auto delaunay (InputIterator begin, InputIterator end) auto delaunay(InputIterator begin, InputIterator end)
{ {
std::vector<Index> edge_queue; std::vector<Index> edge_queue;
@ -58,7 +58,7 @@ namespace cg
auto p3 = e.twin().next().next().origin(); auto p3 = e.twin().next().next().origin();
// decide if a flip is needed // decide if a flip is needed
if (in_circle(*p0.data(), *p1.data(), *p2.data(), *p3.data()) != sign_t::positive) continue; if (in_circle(*p0.data(), *p1.data(), *p2.data(), *p3.data()) != geom::sign_t::positive) continue;
auto f0 = e.face(); auto f0 = e.face();
auto f1 = twin.face(); auto f1 = twin.face();

View file

@ -1,20 +1,20 @@
#pragma once #pragma once
#include <psemek/util/functional.hpp>
#include <psemek/geom/orientation.hpp> #include <psemek/geom/orientation.hpp>
#include <psemek/cg/dcel.hpp> #include <psemek/cg/dcel.hpp>
#include <psemek/cg/utility.hpp>
#include <algorithm> #include <algorithm>
#include <numeric> #include <numeric>
namespace cg namespace psemek::cg
{ {
namespace detail namespace detail
{ {
template <typename Index = std::size_t, typename Iterator, typename Callback> template <typename Index = std::size_t, typename Iterator, typename Callback>
auto triangulate (Iterator begin, Iterator end, Callback && callback) auto triangulate(Iterator begin, Iterator end, Callback && callback)
{ {
using point_type = std::decay_t<decltype(*begin)>; using point_type = std::decay_t<decltype(*begin)>;
static_assert(point_type::dimension == 2); static_assert(point_type::dimension == 2);
@ -93,7 +93,7 @@ namespace cg
bool degenerate = false; bool degenerate = false;
// find first hull edge visible from new point // find first hull edge visible from new point
while (orientation(**it, *hp0.data(), *hp1.data()) != sign_t::positive) while (orientation(**it, *hp0.data(), *hp1.data()) != geom::sign_t::positive)
{ {
move_hull_edge(); move_hull_edge();
if (cur_hull_edge == hull_start) if (cur_hull_edge == hull_start)
@ -192,7 +192,7 @@ namespace cg
} }
// until current edge is visible // until current edge is visible
while (orientation(**it, *hp0.data(), *hp1.data()) == sign_t::positive) while (orientation(**it, *hp0.data(), *hp1.data()) == geom::sign_t::positive)
{ {
// fill new triangle // fill new triangle
@ -254,7 +254,7 @@ namespace cg
} }
template <typename Index = std::size_t, typename InputIterator> template <typename Index = std::size_t, typename InputIterator>
auto triangulate (InputIterator begin, InputIterator end) auto triangulate(InputIterator begin, InputIterator end)
{ {
return detail::triangulate(begin, end, util::nop); return detail::triangulate(begin, end, util::nop);
} }

View file

@ -1,68 +0,0 @@
#pragma once
#include <utility>
#include <variant>
namespace cg::util
{
struct empty{};
template <typename ... Fs>
struct overload_impl
: Fs ...
{
using Fs::operator() ...;
};
template <typename ... Fs>
auto overload (Fs && ... fs)
{
return overload_impl<Fs...>{ std::forward<Fs>(fs) ... };
}
template <typename Variant, typename ... Fs>
decltype(auto) match (Variant && v, Fs && ... fs)
{
return std::visit(overload(std::forward<Fs>(fs)...), std::forward<Variant>(v));
}
constexpr auto id = [](auto const & x){ return x; };
constexpr auto nop = [](auto const & ...){};
namespace detail
{
template <typename T, bool CanInherit>
struct ebo_helper_impl : T
{
T & data() { return *this; }
T const & data() const { return *this; }
template <typename ... Args>
ebo_helper_impl (Args && ... args)
: T(std::forward<Args>(args)...)
{ }
};
template <typename T>
struct ebo_helper_impl<T, false>
{
T value;
T & data() { return value; }
T const & data() const { return value; }
template <typename ... Args>
ebo_helper_impl (Args && ... args)
: value(std::forward<Args>(args)...)
{ }
};
}
template <typename T>
using ebo_helper = detail::ebo_helper_impl<T, std::is_class_v<T> && !(std::is_final_v<T>)>;
}

View file

@ -1,17 +1,17 @@
#pragma once #pragma once
#include <psemek/geom/gauss.hpp>
#include <psemek/cg/triangulation/delaunay.hpp> #include <psemek/cg/triangulation/delaunay.hpp>
#include <psemek/cg/dual.hpp> #include <psemek/cg/dual.hpp>
#include <psemek/geom/gauss.hpp>
#include <psemek/cg/bbox.hpp> #include <psemek/cg/bbox.hpp>
namespace cg namespace psemek::cg
{ {
// Point #0 of the resulting dcel corresponds to the outer face, // Point #0 of the resulting dcel corresponds to the outer face,
// i.e. the point at infinity, and has unspecified coordinates. // i.e. the point at infinity, and has unspecified coordinates.
template <typename Index = std::size_t, typename Iterator> template <typename Index = std::size_t, typename Iterator>
auto voronoi (Iterator begin, Iterator end) auto voronoi(Iterator begin, Iterator end)
{ {
using point_type = std::decay_t<decltype(*begin)>; using point_type = std::decay_t<decltype(*begin)>;
@ -35,8 +35,8 @@ namespace cg
using T = typename point_type::scalar_type; using T = typename point_type::scalar_type;
matrix<T, 3, 3> m; geom::matrix<T, 3, 3> m;
vector<T, 3> b; geom::vector<T, 3> b;
for (std::size_t i = 0; i < 3; ++i) for (std::size_t i = 0; i < 3; ++i)
{ {
@ -47,7 +47,7 @@ namespace cg
b[i] = q[i][0] * q[i][0] + q[i][1] * q[i][1]; b[i] = q[i][0] * q[i][0] + q[i][1] * q[i][1];
} }
gauss(m, b); geom::gauss(m, b);
auto newp = result.push_point(point_type{b[0] / 2, b[1] / 2}); auto newp = result.push_point(point_type{b[0] / 2, b[1] / 2});
newp.edge(result.edge(p.edge().index())); newp.edge(result.edge(p.edge().index()));
@ -61,7 +61,7 @@ namespace cg
// Replaces the #0 infinite point of a dcel with a proper outer face // Replaces the #0 infinite point of a dcel with a proper outer face
template <typename Point, typename Face, typename Edge, typename Index> template <typename Point, typename Face, typename Edge, typename Index>
void remove_infinite_point (dcel<Point, Face, Edge, Index> & dcel) void remove_infinite_point(dcel<Point, Face, Edge, Index> & dcel)
{ {
// insert outer face at position #0 // insert outer face at position #0
auto outer_face = dcel.insert_face(0); auto outer_face = dcel.insert_face(0);
@ -117,7 +117,7 @@ namespace cg
// iteratively removes degenerate edges // iteratively removes degenerate edges
template <typename Point, typename Face, typename Edge, typename Index> template <typename Point, typename Face, typename Edge, typename Index>
void remove_degenerate_edges (dcel<Point, Face, Edge, Index> & dcel) void remove_degenerate_edges(dcel<Point, Face, Edge, Index> & dcel)
{ {
std::vector<std::size_t> delete_points; std::vector<std::size_t> delete_points;
std::vector<std::size_t> delete_edges; std::vector<std::size_t> delete_edges;
@ -160,7 +160,7 @@ namespace cg
// Outputs 4 points such that the finite faces of the voronoi diagram of (anything // Outputs 4 points such that the finite faces of the voronoi diagram of (anything
// inside the convex hull of input + the output points) covers the convex hull of input // inside the convex hull of input + the output points) covers the convex hull of input
template <typename InputIterator, typename OutputIterator> template <typename InputIterator, typename OutputIterator>
OutputIterator bounded_voronoi_extra_points (InputIterator begin, InputIterator end, OutputIterator out) OutputIterator bounded_voronoi_extra_points(InputIterator begin, InputIterator end, OutputIterator out)
{ {
using point_type = std::decay_t<decltype(*begin)>; using point_type = std::decay_t<decltype(*begin)>;
@ -183,7 +183,7 @@ namespace cg
// Compute a clipped voronoi tessellation of (begin, end - 4) // Compute a clipped voronoi tessellation of (begin, end - 4)
// Last 4 points will be used for temporary data // Last 4 points will be used for temporary data
template <typename InputIterator> template <typename InputIterator>
auto bounded_voronoi (InputIterator begin, InputIterator end) auto bounded_voronoi(InputIterator begin, InputIterator end)
{ {
bounded_voronoi_extra_points(begin, end - 4, end - 4); bounded_voronoi_extra_points(begin, end - 4, end - 4);
auto dcel = cg::voronoi(begin, end); auto dcel = cg::voronoi(begin, end);

View file

@ -4,6 +4,6 @@ find_package(GMP REQUIRED)
file(GLOB_RECURSE PSEMEK_GEOM_HEADERS "include/*.hpp") file(GLOB_RECURSE PSEMEK_GEOM_HEADERS "include/*.hpp")
file(GLOB_RECURSE PSEMEK_GEOM_SOURCES "source/*.cpp") file(GLOB_RECURSE PSEMEK_GEOM_SOURCES "source/*.cpp")
add_library(geom STATIC ${PSEMEK_GEOM_HEADERS} ${PSEMEK_GEOM_SOURCES}) add_library(geom ${PSEMEK_GEOM_HEADERS} ${PSEMEK_GEOM_SOURCES})
target_include_directories(geom PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include") target_include_directories(geom PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include")
target_link_libraries(geom PUBLIC Boost::boost GMP) target_link_libraries(geom PUBLIC util Boost::boost GMP)

View file

@ -11,7 +11,7 @@ namespace psemek::geom
template <typename Point> template <typename Point>
struct bezier struct bezier
{ {
bezier (std::vector<Point> points) bezier(std::vector<Point> points)
: points_(std::move(points)) : points_(std::move(points))
{ {
if (points_.empty()) if (points_.empty())
@ -20,7 +20,7 @@ namespace psemek::geom
} }
template <typename T> template <typename T>
auto operator() (T const & t) const auto operator()(T const & t) const
{ {
// In-place de Casteljau's algorithm // In-place de Casteljau's algorithm
temp_ = points_; temp_ = points_;

View file

@ -14,18 +14,18 @@ namespace psemek::geom
using point_type = point<T, N>; using point_type = point<T, N>;
using vector_type = vector<T, N>; using vector_type = vector<T, N>;
interval<T> & operator [] (std::size_t i) interval<T> & operator[](std::size_t i)
{ {
return axes[i]; return axes[i];
} }
interval<T> const & operator [] (std::size_t i) const interval<T> const & operator[](std::size_t i) const
{ {
return axes[i]; return axes[i];
} }
// singleton box // singleton box
static box singleton (point_type const & p) static box singleton(point_type const & p)
{ {
box b; box b;
for (std::size_t i = 0; i < N; ++i) for (std::size_t i = 0; i < N; ++i)
@ -33,7 +33,7 @@ namespace psemek::geom
return b; return b;
} }
bool empty ( ) const bool empty() const
{ {
for (auto const & i : axes) for (auto const & i : axes)
if (i.empty()) if (i.empty())
@ -41,7 +41,7 @@ namespace psemek::geom
return false; return false;
} }
T size ( ) const T size() const
{ {
T result = T{1}; T result = T{1};
for (auto const & i : axes) for (auto const & i : axes)

View file

@ -10,13 +10,13 @@ namespace psemek::geom
{ {
template <typename T> template <typename T>
bool contains (interval<T> const & i, T const & x) bool contains(interval<T> const & i, T const & x)
{ {
return (i.min <= x) && (x <= i.max); return (i.min <= x) && (x <= i.max);
} }
template <typename T, std::size_t N> template <typename T, std::size_t N>
bool contains (box<T, N> const & b, point<T, N> const & p) bool contains(box<T, N> const & b, point<T, N> const & p)
{ {
for (std::size_t i = 0; i < N; ++i) for (std::size_t i = 0; i < N; ++i)
if (!contains(b[i], p[i])) if (!contains(b[i], p[i]))
@ -25,7 +25,7 @@ namespace psemek::geom
} }
template <typename T> template <typename T>
bool contains (triangle<point<T, 2>> const & t, point<T, 2> const & p) bool contains(triangle<point<T, 2>> const & t, point<T, 2> const & p)
{ {
return true return true
&& orientation(t[0], t[1], p) != sign_t::negative && orientation(t[0], t[1], p) != sign_t::negative

View file

@ -16,15 +16,15 @@ namespace psemek::geom
struct gauss_helper; struct gauss_helper;
template <typename X> template <typename X>
gauss_helper (X &) -> gauss_helper<X>; gauss_helper(X &) -> gauss_helper<X>;
template <typename T, std::size_t N> template <typename T, std::size_t N>
struct gauss_helper<vector<T, N>> struct gauss_helper<vector<T, N>>
{ {
vector<T, N> & v; vector<T, N> & v;
static constexpr std::size_t columns ( ) { return 1; } static constexpr std::size_t columns() { return 1; }
T & at (std::size_t row, std::size_t) { return v[row]; } T & at(std::size_t row, std::size_t) { return v[row]; }
}; };
template <typename T, std::size_t N, std::size_t M> template <typename T, std::size_t N, std::size_t M>
@ -32,12 +32,12 @@ namespace psemek::geom
{ {
matrix<T, N, M> & m; matrix<T, N, M> & m;
static constexpr std::size_t columns ( ) { return M; } static constexpr std::size_t columns() { return M; }
T & at (std::size_t row, std::size_t col) { return m[row][col]; } T & at(std::size_t row, std::size_t col) { return m[row][col]; }
}; };
template <typename F, typename ... Args> template <typename F, typename ... Args>
void for_each (F && f, Args & ... args) void for_each(F && f, Args & ... args)
{ {
(f(args), ...); (f(args), ...);
} }
@ -45,7 +45,7 @@ namespace psemek::geom
} }
template <typename T, std::size_t N> template <typename T, std::size_t N>
T det (matrix<T, N, N> m) T det(matrix<T, N, N> m)
{ {
using std::abs; using std::abs;
@ -101,7 +101,7 @@ namespace psemek::geom
// the set of equations (m * x = rhs)... is solved simultaneously column-wise // the set of equations (m * x = rhs)... is solved simultaneously column-wise
// returns false is the matrix is degenerate // returns false is the matrix is degenerate
template <typename T, std::size_t N, typename ... RHS> template <typename T, std::size_t N, typename ... RHS>
bool gauss (matrix<T, N, N> m, RHS & ... rhs) bool gauss(matrix<T, N, N> m, RHS & ... rhs)
{ {
using std::abs; using std::abs;
@ -198,7 +198,7 @@ namespace psemek::geom
} }
template <typename T, std::size_t N> template <typename T, std::size_t N>
std::optional<matrix<T, N, N>> inverse (matrix<T, N, N> m) std::optional<matrix<T, N, N>> inverse(matrix<T, N, N> m)
{ {
matrix<T, N, N> r = matrix<T, N, N>::identity(); matrix<T, N, N> r = matrix<T, N, N>::identity();
if (!gauss(m, r)) if (!gauss(m, r))
@ -208,7 +208,7 @@ namespace psemek::geom
// Least-squares solution of m*x=b with full-rank m // Least-squares solution of m*x=b with full-rank m
template <typename T, std::size_t N, std::size_t M> template <typename T, std::size_t N, std::size_t M>
std::optional<vector<T, M>> least_squares (matrix<T, N, M> const & m, vector<T, N> const & b) std::optional<vector<T, M>> least_squares(matrix<T, N, M> const & m, vector<T, N> const & b)
{ {
if constexpr (N == M) if constexpr (N == M)
{ {

View file

@ -13,9 +13,10 @@ namespace psemek::geom
template <typename T> template <typename T>
std::enable_if_t<!std::is_floating_point_v<T>, sign_t> std::enable_if_t<!std::is_floating_point_v<T>, sign_t>
in_circle (point<T, 2> const & p0, point<T, 2> const & p1, point<T, 2> const & p2, point<T, 2> const & p3) in_circle(point<T, 2> const & p0, point<T, 2> const & p1, point<T, 2> const & p2, point<T, 2> const & p3)
{ {
auto proj = [](point<T, 2> const & p){ auto proj = [](point<T, 2> const & p)
{
auto const x = p[0]; auto const x = p[0];
auto const y = p[1]; auto const y = p[1];
return point<T, 3>{ x, y, x*x + y*y }; return point<T, 3>{ x, y, x*x + y*y };
@ -26,7 +27,7 @@ namespace psemek::geom
template <typename T> template <typename T>
std::enable_if_t<std::is_floating_point_v<T>, sign_t> std::enable_if_t<std::is_floating_point_v<T>, sign_t>
in_circle (point<T, 2> const & p0, point<T, 2> const & p1, point<T, 2> const & p2, point<T, 2> const & p3) in_circle(point<T, 2> const & p0, point<T, 2> const & p1, point<T, 2> const & p2, point<T, 2> const & p3)
{ {
constexpr T error = std::numeric_limits<T>::epsilon() * T(29) / T(2); constexpr T error = std::numeric_limits<T>::epsilon() * T(29) / T(2);

View file

@ -1,5 +1,7 @@
#pragma once #pragma once
#include <psemek/util/empty.hpp>
#include <psemek/geom/simplex.hpp> #include <psemek/geom/simplex.hpp>
#include <psemek/geom/orientation.hpp> #include <psemek/geom/orientation.hpp>
#include <psemek/geom/contains.hpp> #include <psemek/geom/contains.hpp>
@ -10,17 +12,8 @@
namespace psemek::geom namespace psemek::geom
{ {
// denotes empty intersection
struct empty { };
template <typename Stream>
Stream & operator << (Stream & os, empty)
{
return os << "empty";
}
template <typename Point, typename = std::enable_if_t<Point::dimension == 2>> template <typename Point, typename = std::enable_if_t<Point::dimension == 2>>
bool intersect (segment<Point> const & s0, segment<Point> const & s1) bool intersect(segment<Point> const & s0, segment<Point> const & s1)
{ {
auto const o00 = orientation(s0[0], s0[1], s1[0]); auto const o00 = orientation(s0[0], s0[1], s1[0]);
auto const o01 = orientation(s0[0], s0[1], s1[1]); auto const o01 = orientation(s0[0], s0[1], s1[1]);
@ -32,7 +25,7 @@ namespace psemek::geom
// TODO: robust implementation // TODO: robust implementation
template <typename Point, typename = std::enable_if_t<Point::dimension == 2>> template <typename Point, typename = std::enable_if_t<Point::dimension == 2>>
std::variant<empty, Point, segment<Point>> intersection (segment<Point> s0, segment<Point> s1) std::variant<util::empty, Point, segment<Point>> intersection(segment<Point> s0, segment<Point> s1)
{ {
auto const a0 = -det(s1[0] - s0[0], s1[1] - s1[0]); auto const a0 = -det(s1[0] - s0[0], s1[1] - s1[0]);
auto const a1 = det(s0[1] - s0[0], s1[0] - s0[0]); auto const a1 = det(s0[1] - s0[0], s1[0] - s0[0]);
@ -46,7 +39,7 @@ namespace psemek::geom
auto const t1 = a1 / b; auto const t1 = a1 / b;
if (t0 < 0 || t0 > 1 || t1 < 0 || t1 > 1) if (t0 < 0 || t0 > 1 || t1 < 0 || t1 > 1)
return empty{}; return util::empty{};
return s0[0] + t0 * (s0[1] - s0[0]); return s0[0] + t0 * (s0[1] - s0[0]);
} }
@ -57,7 +50,7 @@ namespace psemek::geom
if (a0 != 0) if (a0 != 0)
{ {
// segments do not lie on the same line: no intersection // segments do not lie on the same line: no intersection
return empty{}; return util::empty{};
} }
// if segments are not Y-axis aligned, safe to use X-coordinates to sort them (k = 0) // if segments are not Y-axis aligned, safe to use X-coordinates to sort them (k = 0)
@ -74,7 +67,7 @@ namespace psemek::geom
auto const r1 = std::min(s0[1][k], s1[1][k]); auto const r1 = std::min(s0[1][k], s1[1][k]);
if (r0 > r1) if (r0 > r1)
return empty{}; return util::empty{};
bool const s0_is_first = s0[0][k] < s1[0][k]; bool const s0_is_first = s0[0][k] < s1[0][k];

View file

@ -11,7 +11,7 @@ namespace psemek::geom
template <typename T> template <typename T>
struct limits struct limits
{ {
static constexpr T min ( ) static constexpr T min()
{ {
if constexpr (std::is_floating_point_v<T>) if constexpr (std::is_floating_point_v<T>)
{ {
@ -23,7 +23,7 @@ namespace psemek::geom
} }
} }
static constexpr T max ( ) static constexpr T max()
{ {
if constexpr (std::is_floating_point_v<T>) if constexpr (std::is_floating_point_v<T>)
{ {
@ -42,15 +42,15 @@ namespace psemek::geom
{ {
T value; T value;
T operator* () const { return value; } T operator*() const { return value; }
interval_iterator & operator++ () interval_iterator & operator++()
{ {
++value; ++value;
return *this; return *this;
} }
interval_iterator operator++ (int) interval_iterator operator++(int)
{ {
auto copy = *this; auto copy = *this;
++value; ++value;
@ -74,17 +74,17 @@ namespace psemek::geom
T min = limits<T>::max(); T min = limits<T>::max();
T max = limits<T>::min(); T max = limits<T>::min();
static interval singleton (T const & value) static interval singleton(T const & value)
{ {
return {value, value}; return {value, value};
} }
bool empty ( ) const bool empty() const
{ {
return min > max; return min > max;
} }
T length ( ) const T length() const
{ {
return empty() ? T{} : max - min; return empty() ? T{} : max - min;
} }
@ -208,7 +208,7 @@ namespace psemek::geom
} }
template <typename T> template <typename T>
T clamp (T x, interval<T> const & i) T clamp(T x, interval<T> const & i)
{ {
return std::max(i.min, std::min(i.max, x)); return std::max(i.min, std::min(i.max, x));
} }

View file

@ -17,12 +17,12 @@ namespace psemek::geom
T coords[R * C]; T coords[R * C];
T * operator [] (std::size_t i) T * operator[](std::size_t i)
{ {
return coords + C * i; return coords + C * i;
} }
T const * operator [] (std::size_t i) const T const * operator[](std::size_t i) const
{ {
return coords + C * i; return coords + C * i;
} }
@ -33,14 +33,14 @@ namespace psemek::geom
matrix & operator += (matrix const & v); matrix & operator += (matrix const & v);
matrix & operator -= (matrix const & v); matrix & operator -= (matrix const & v);
static matrix zero ( ); static matrix zero();
static matrix identity ( ); static matrix identity();
static matrix scalar (T const & s); static matrix scalar(T const & s);
}; };
template <typename T, std::size_t R, std::size_t C> template <typename T, std::size_t R, std::size_t C>
matrix<T, R, C> matrix<T, R, C>::zero ( ) matrix<T, R, C> matrix<T, R, C>::zero()
{ {
matrix<T, R, C> m; matrix<T, R, C> m;
for (std::size_t i = 0; i < R * C; ++i) for (std::size_t i = 0; i < R * C; ++i)
@ -49,13 +49,13 @@ namespace psemek::geom
} }
template <typename T, std::size_t R, std::size_t C> template <typename T, std::size_t R, std::size_t C>
matrix<T, R, C> matrix<T, R, C>::identity ( ) matrix<T, R, C> matrix<T, R, C>::identity()
{ {
return scalar(T{1}); return scalar(T{1});
} }
template <typename T, std::size_t R, std::size_t C> template <typename T, std::size_t R, std::size_t C>
matrix<T, R, C> matrix<T, R, C>::scalar (T const & s) matrix<T, R, C> matrix<T, R, C>::scalar(T const & s)
{ {
matrix<T, R, C> m = zero(); matrix<T, R, C> m = zero();
for (std::size_t i = 0; i < std::min(R, C); ++i) for (std::size_t i = 0; i < std::min(R, C); ++i)
@ -101,7 +101,7 @@ namespace psemek::geom
} }
template <typename T1, typename T, std::size_t R, std::size_t C> template <typename T1, typename T, std::size_t R, std::size_t C>
matrix<T1, R, C> cast (matrix<T, R, C> const & m) matrix<T1, R, C> cast(matrix<T, R, C> const & m)
{ {
matrix<T1, R, C> r; matrix<T1, R, C> r;
for (std::size_t i = 0; i < R * C; ++i) for (std::size_t i = 0; i < R * C; ++i)
@ -226,7 +226,7 @@ namespace psemek::geom
} }
template <typename T, std::size_t R, std::size_t C> template <typename T, std::size_t R, std::size_t C>
matrix<T, C, R> transpose (matrix<T, R, C> const & m) matrix<T, C, R> transpose(matrix<T, R, C> const & m)
{ {
matrix<T, C, R> r; matrix<T, C, R> r;
for (std::size_t i = 0; i < R; ++i) for (std::size_t i = 0; i < R; ++i)

View file

@ -15,7 +15,7 @@ namespace psemek::geom
// TODO: generic implementation // TODO: generic implementation
template <typename T> template <typename T>
std::enable_if_t<!std::is_floating_point_v<T>, sign_t> std::enable_if_t<!std::is_floating_point_v<T>, sign_t>
orientation (point<T, 2> const & p0, point<T, 2> const & p1, point<T, 2> const & p2) orientation(point<T, 2> const & p0, point<T, 2> const & p1, point<T, 2> const & p2)
{ {
T const d = det(p1 - p0, p2 - p0); T const d = det(p1 - p0, p2 - p0);
@ -29,7 +29,7 @@ namespace psemek::geom
template <typename T> template <typename T>
std::enable_if_t<std::is_floating_point_v<T>, sign_t> std::enable_if_t<std::is_floating_point_v<T>, sign_t>
orientation (point<T, 2> const & p0, point<T, 2> const & p1, point<T, 2> const & p2) orientation(point<T, 2> const & p0, point<T, 2> const & p1, point<T, 2> const & p2)
{ {
constexpr T error = std::numeric_limits<T>::epsilon() * T(5) / T(2); constexpr T error = std::numeric_limits<T>::epsilon() * T(5) / T(2);
@ -52,7 +52,7 @@ namespace psemek::geom
} }
template <typename T> template <typename T>
sign_t orientation (point<T, 3> const & p0, point<T, 3> const & p1, point<T, 3> const & p2, point<T, 3> const & p3) sign_t orientation(point<T, 3> const & p0, point<T, 3> const & p1, point<T, 3> const & p2, point<T, 3> const & p3)
{ {
T const d = det(p0 - p3, p1 - p3, p2 - p3); T const d = det(p0 - p3, p1 - p3, p2 - p3);

View file

@ -12,10 +12,10 @@ namespace psemek::geom
template <typename T, std::size_t D> template <typename T, std::size_t D>
struct orthographic struct orthographic
{ {
using vector_type = vector<T, D>; using vector_type = geom::vector<T, D>;
using point_type = point<T, D>; using point_type = geom::point<T, D>;
using homogeneous_matrix_type = matrix<T, D + 1, D + 1>; using homogeneous_matrix_type = geom::matrix<T, D + 1, D + 1>;
using box_type = box<T, D>; using box_type = geom::box<T, D>;
orthographic(); orthographic();
orthographic(box_type r); orthographic(box_type r);
@ -46,7 +46,7 @@ namespace psemek::geom
template <typename T, std::size_t D> template <typename T, std::size_t D>
orthographic<T, D>::orthographic(box_type r) orthographic<T, D>::orthographic(box_type r)
: r_(r) : r_(r)
{ } {}
template <typename T, std::size_t D> template <typename T, std::size_t D>
box<T, D> orthographic<T, D>::box() const box<T, D> orthographic<T, D>::box() const
@ -89,4 +89,20 @@ namespace psemek::geom
return m; return m;
} }
template <typename T, std::size_t D>
orthographic<T, D> orthographic<T, D>::inverse() const
{
auto inv = [](interval<T> const & i)
{
auto const s = i.length();
auto const d = i.max - i.min;
return interval<T>{ (- s - 2) / d, (- s + 2) / d };
};
box_type inv_box;
for (std::size_t d = 0; d < D; ++d)
inv_box[d] = inv(r_[d]);
return {inv_box};
}
} }

View file

@ -10,13 +10,13 @@ namespace psemek::geom
template <typename T, std::size_t D> template <typename T, std::size_t D>
struct swap struct swap
{ {
using vector_type = vector<T, D>; using vector_type = geom::vector<T, D>;
using point_type = point<T, D>; using point_type = geom::point<T, D>;
using matrix_type = matrix<T, D, D>; using matrix_type = geom::matrix<T, D, D>;
swap(std::size_t i, std::size_t j); swap(std::size_t i, std::size_t j);
vector_type operator() (vector_type v) const; vector_type operator()(vector_type v) const;
matrix_type matrix() const; matrix_type matrix() const;
@ -27,13 +27,13 @@ namespace psemek::geom
}; };
template <typename T, std::size_t D> template <typename T, std::size_t D>
swap<T, D>::swap (std::size_t i, std::size_t j) swap<T, D>::swap(std::size_t i, std::size_t j)
: i_(i) : i_(i)
, j_(j) , j_(j)
{ } {}
template <typename T, std::size_t D> template <typename T, std::size_t D>
vector<T, D> swap<T, D>::operator() (vector_type v) const vector<T, D> swap<T, D>::operator()(vector_type v) const
{ {
std::swap(v[i_], v[j_]); std::swap(v[i_], v[j_]);
return v; return v;

View file

@ -16,9 +16,9 @@ namespace psemek::geom
using homogeneous_matrix_type = matrix<T, 4, 4>; using homogeneous_matrix_type = matrix<T, 4, 4>;
// fov are in radians // fov are in radians
perspective (scalar_type fov_x, scalar_type fov_y, scalar_type near, scalar_type far); perspective(scalar_type fov_x, scalar_type fov_y, scalar_type near, scalar_type far);
perspective (scalar_type left, scalar_type right, scalar_type bottom, scalar_type top, scalar_type near, scalar_type far); perspective(scalar_type left, scalar_type right, scalar_type bottom, scalar_type top, scalar_type near, scalar_type far);
homogeneous_matrix_type homogeneous_matrix() const; homogeneous_matrix_type homogeneous_matrix() const;

View file

@ -14,27 +14,27 @@ namespace psemek::geom
T coords[N]; T coords[N];
point ( ) = default; point() = default;
point (point const &) = default; point(point const &) = default;
point (point &) = default; point(point &) = default;
point (point &&) = default; point(point &&) = default;
point & operator = (point const &) = default; point & operator = (point const &) = default;
point & operator = (point &) = default; point & operator = (point &) = default;
point & operator = (point &&) = default; point & operator = (point &&) = default;
template <typename ... Args> template <typename ... Args>
point (Args && ... args) point(Args && ... args)
: coords{ std::forward<Args>(args)... } : coords{ std::forward<Args>(args)... }
{ {
static_assert(sizeof...(Args) == N); static_assert(sizeof...(Args) == N);
} }
T & operator[] (std::size_t i) T & operator[](std::size_t i)
{ {
return coords[i]; return coords[i];
} }
T const & operator[] (std::size_t i) const T const & operator[](std::size_t i) const
{ {
return coords[i]; return coords[i];
} }
@ -44,7 +44,7 @@ namespace psemek::geom
}; };
template <typename ... Args> template <typename ... Args>
point (Args && ...) -> point<std::common_type_t<Args...>, sizeof...(Args)>; point(Args && ...) -> point<std::common_type_t<Args...>, sizeof...(Args)>;
template <typename T, std::size_t N> template <typename T, std::size_t N>
bool operator == (point<T, N> const & p1, point<T, N> const & p2) bool operator == (point<T, N> const & p1, point<T, N> const & p2)
@ -86,7 +86,7 @@ namespace psemek::geom
} }
template <typename T1, typename T, std::size_t N> template <typename T1, typename T, std::size_t N>
point<T1, N> cast (point<T, N> const & p) point<T1, N> cast(point<T, N> const & p)
{ {
point<T1, N> r; point<T1, N> r;
for (std::size_t i = 0; i < N; ++i) for (std::size_t i = 0; i < N; ++i)
@ -143,19 +143,19 @@ namespace psemek::geom
} }
template <typename T, std::size_t N> template <typename T, std::size_t N>
point<T, N> lerp (point<T, N> const & p0, point<T, N> const & p1, T const & t) point<T, N> lerp(point<T, N> const & p0, point<T, N> const & p1, T const & t)
{ {
return p0 + t * (p1 - p0); return p0 + t * (p1 - p0);
} }
template <typename T, std::size_t N> template <typename T, std::size_t N>
T distance_sqr (point<T, N> const & p1, point<T, N> const & p2) T distance_sqr(point<T, N> const & p1, point<T, N> const & p2)
{ {
return length_sqr(p2 - p1); return length_sqr(p2 - p1);
} }
template <typename T, std::size_t N> template <typename T, std::size_t N>
T distance (point<T, N> const & p1, point<T, N> const & p2) T distance(point<T, N> const & p1, point<T, N> const & p2)
{ {
return length(p2 - p1); return length(p2 - p1);
} }

View file

@ -22,7 +22,7 @@ namespace psemek::geom
scalar_type angle() const; scalar_type angle() const;
scalar_type angle(scalar_type a); scalar_type angle(scalar_type a);
vector_type operator() (vector_type v) const; vector_type operator()(vector_type v) const;
matrix_type matrix() const; matrix_type matrix() const;
@ -52,7 +52,7 @@ namespace psemek::geom
scalar_type angle() const; scalar_type angle() const;
scalar_type angle(scalar_type a); scalar_type angle(scalar_type a);
vector_type operator() (vector_type v) const; vector_type operator()(vector_type v) const;
matrix_type matrix() const; matrix_type matrix() const;
@ -66,7 +66,7 @@ namespace psemek::geom
template <typename T, std::size_t D> template <typename T, std::size_t D>
plane_rotation<T, D>::plane_rotation(std::size_t i, std::size_t j, T angle) plane_rotation<T, D>::plane_rotation(std::size_t i, std::size_t j, T angle)
: i_(i), j_(j), angle_(angle) : i_(i), j_(j), angle_(angle)
{ } {}
template <typename T, std::size_t D> template <typename T, std::size_t D>
T plane_rotation<T, D>::angle() const T plane_rotation<T, D>::angle() const
@ -83,7 +83,7 @@ namespace psemek::geom
} }
template <typename T, std::size_t D> template <typename T, std::size_t D>
vector<T, D> plane_rotation<T, D>::operator() (vector_type v) const vector<T, D> plane_rotation<T, D>::operator()(vector_type v) const
{ {
T vi = v[i_] * std::cos(angle_) - v[j_] * std::sin(angle_); T vi = v[i_] * std::cos(angle_) - v[j_] * std::sin(angle_);
T vj = v[i_] * std::sin(angle_) + v[j_] * std::cos(angle_); T vj = v[i_] * std::sin(angle_) + v[j_] * std::cos(angle_);
@ -112,13 +112,13 @@ namespace psemek::geom
template <typename T> template <typename T>
axis_rotation<T>::axis_rotation() axis_rotation<T>::axis_rotation()
: axis_rotation(vector_type{T(0), T(0), T(1)}, T(0)) : axis_rotation(vector_type{T(0), T(0), T(1)}, T(0))
{ } {}
template <typename T> template <typename T>
axis_rotation<T>::axis_rotation(vector_type axis, scalar_type angle) axis_rotation<T>::axis_rotation(vector_type axis, scalar_type angle)
: axis_(axis) : axis_(axis)
, angle_(angle) , angle_(angle)
{ } {}
template <typename T> template <typename T>
vector<T, 3> axis_rotation<T>::axis() const vector<T, 3> axis_rotation<T>::axis() const
@ -135,7 +135,7 @@ namespace psemek::geom
} }
template <typename T> template <typename T>
T axis_rotation<T>::angle ( ) const T axis_rotation<T>::angle() const
{ {
return angle_; return angle_;
} }
@ -149,7 +149,7 @@ namespace psemek::geom
} }
template <typename T> template <typename T>
vector<T, 3> axis_rotation<T>::operator() (vector_type v) const vector<T, 3> axis_rotation<T>::operator()(vector_type v) const
{ {
return matrix() * v; return matrix() * v;
} }

View file

@ -10,9 +10,9 @@ namespace psemek::geom
template <typename T, std::size_t D> template <typename T, std::size_t D>
struct scale struct scale
{ {
using vector_type = vector<T, D>; using vector_type = geom::vector<T, D>;
using point_type = point<T, D>; using point_type = geom::point<T, D>;
using matrix_type = matrix<T, D, D>; using matrix_type = geom::matrix<T, D, D>;
scale(); scale();
scale(T v); scale(T v);
@ -21,7 +21,7 @@ namespace psemek::geom
vector_type vector() const; vector_type vector() const;
vector_type vector(vector_type v); vector_type vector(vector_type v);
vector_type operator() (vector_type v) const; vector_type operator()(vector_type v) const;
matrix_type matrix() const; matrix_type matrix() const;
@ -48,7 +48,7 @@ namespace psemek::geom
template <typename T, std::size_t D> template <typename T, std::size_t D>
scale<T, D>::scale(vector_type v) scale<T, D>::scale(vector_type v)
: v_(v) : v_(v)
{ } {}
template <typename T, std::size_t D> template <typename T, std::size_t D>
vector<T, D> scale<T, D>::vector() const vector<T, D> scale<T, D>::vector() const
@ -65,7 +65,7 @@ namespace psemek::geom
} }
template <typename T, std::size_t D> template <typename T, std::size_t D>
vector<T, D> scale<T, D>::operator() (vector_type v) const vector<T, D> scale<T, D>::operator()(vector_type v) const
{ {
for (std::size_t i = 0; i < D; ++i) for (std::size_t i = 0; i < D; ++i)
v[i] *= v_[i]; v[i] *= v_[i];

View file

@ -14,35 +14,35 @@ namespace psemek::geom
point_type points[K + 1]; point_type points[K + 1];
point_type & operator[] (std::size_t i) point_type & operator[](std::size_t i)
{ {
return points[i]; return points[i];
} }
point_type const & operator[] (std::size_t i) const point_type const & operator[](std::size_t i) const
{ {
return points[i]; return points[i];
} }
}; };
template <typename ... Args> template <typename ... Args>
simplex (Args ...) -> simplex<std::common_type_t<Args...>, sizeof...(Args) - 1>; simplex(Args ...) -> simplex<std::common_type_t<Args...>, sizeof...(Args) - 1>;
template <typename Point> template <typename Point>
struct segment struct segment
: simplex<Point, 1> : simplex<Point, 1>
{ }; {};
template <typename Point> template <typename Point>
segment (Point, Point) -> segment<Point>; segment(Point, Point) -> segment<Point>;
template <typename Point> template <typename Point>
struct triangle struct triangle
: simplex<Point, 2> : simplex<Point, 2>
{ }; {};
template <typename Point> template <typename Point>
triangle (Point, Point, Point) -> triangle<Point>; triangle(Point, Point, Point) -> triangle<Point>;
template <typename Stream, typename Point, std::size_t K> template <typename Stream, typename Point, std::size_t K>
Stream & operator << (Stream & os, simplex<Point, K> const & s) Stream & operator << (Stream & os, simplex<Point, K> const & s)

View file

@ -20,8 +20,8 @@ namespace psemek::geom
vector_type vector() const; vector_type vector() const;
vector_type vector(vector_type v); vector_type vector(vector_type v);
vector_type operator() (vector_type v) const; vector_type operator()(vector_type v) const;
point_type operator() (point_type p) const; point_type operator()(point_type p) const;
homogeneous_matrix_type homogeneous_matrix() const; homogeneous_matrix_type homogeneous_matrix() const;
@ -34,12 +34,12 @@ namespace psemek::geom
template <typename T, std::size_t D> template <typename T, std::size_t D>
translation<T, D>::translation() translation<T, D>::translation()
: translation(vector_type::zero()) : translation(vector_type::zero())
{ } {}
template <typename T, std::size_t D> template <typename T, std::size_t D>
translation<T, D>::translation(vector_type v) translation<T, D>::translation(vector_type v)
: v_(v) : v_(v)
{ } {}
template <typename T, std::size_t D> template <typename T, std::size_t D>
vector<T, D> translation<T, D>::vector() const vector<T, D> translation<T, D>::vector() const
@ -56,13 +56,13 @@ namespace psemek::geom
} }
template <typename T, std::size_t D> template <typename T, std::size_t D>
vector<T, D> translation<T, D>::operator() (vector_type v) const vector<T, D> translation<T, D>::operator()(vector_type v) const
{ {
return v; return v;
} }
template <typename T, std::size_t D> template <typename T, std::size_t D>
point<T, D> translation<T, D>::operator() (point_type p) const point<T, D> translation<T, D>::operator()(point_type p) const
{ {
return p + v_; return p + v_;
} }

View file

@ -17,27 +17,27 @@ namespace psemek::geom
T coords[N]; T coords[N];
vector ( ) = default; vector() = default;
vector (vector const &) = default; vector(vector const &) = default;
vector (vector &) = default; vector(vector &) = default;
vector (vector &&) = default; vector(vector &&) = default;
vector & operator = (vector const &) = default; vector & operator = (vector const &) = default;
vector & operator = (vector &) = default; vector & operator = (vector &) = default;
vector & operator = (vector &&) = default; vector & operator = (vector &&) = default;
template <typename ... Args> template <typename ... Args>
vector (Args && ... args) vector(Args && ... args)
: coords{ std::forward<Args>(args)... } : coords{ std::forward<Args>(args)... }
{ {
static_assert(sizeof...(Args) == N); static_assert(sizeof...(Args) == N);
} }
T & operator[] (std::size_t i) T & operator[](std::size_t i)
{ {
return coords[i]; return coords[i];
} }
T const & operator[] (std::size_t i) const T const & operator[](std::size_t i) const
{ {
return coords[i]; return coords[i];
} }
@ -52,7 +52,7 @@ namespace psemek::geom
}; };
template <typename ... Args> template <typename ... Args>
vector (Args && ...) -> vector<std::common_type_t<Args...>, sizeof...(Args)>; vector(Args && ...) -> vector<std::common_type_t<Args...>, sizeof...(Args)>;
template <typename T, std::size_t N> template <typename T, std::size_t N>
bool operator == (vector<T, N> const & v1, vector<T, N> const & v2) bool operator == (vector<T, N> const & v1, vector<T, N> const & v2)
@ -91,7 +91,7 @@ namespace psemek::geom
} }
template <typename T1, typename T, std::size_t N> template <typename T1, typename T, std::size_t N>
vector<T1, N> cast (vector<T, N> const & v) vector<T1, N> cast(vector<T, N> const & v)
{ {
vector<T1, N> r; vector<T1, N> r;
for (std::size_t i = 0; i < N; ++i) for (std::size_t i = 0; i < N; ++i)
@ -187,7 +187,7 @@ namespace psemek::geom
} }
template <typename T, std::size_t N> template <typename T, std::size_t N>
T dot (vector<T, N> const & v1, vector<T, N> const & v2) T dot(vector<T, N> const & v1, vector<T, N> const & v2)
{ {
T r{}; T r{};
for (std::size_t i = 0; i < N; ++i) for (std::size_t i = 0; i < N; ++i)
@ -196,32 +196,32 @@ namespace psemek::geom
} }
template <typename T, std::size_t N> template <typename T, std::size_t N>
T length_sqr (vector<T, N> const & v) T length_sqr(vector<T, N> const & v)
{ {
return dot(v, v); return dot(v, v);
} }
template <typename T, std::size_t N> template <typename T, std::size_t N>
T length (vector<T, N> const & v) T length(vector<T, N> const & v)
{ {
return std::sqrt(length_sqr(v)); return std::sqrt(length_sqr(v));
} }
template <typename T, std::size_t N> template <typename T, std::size_t N>
vector<T, N> normalized (vector<T, N> const & v) vector<T, N> normalized(vector<T, N> const & v)
{ {
return v / length(v); return v / length(v);
} }
// TODO: generic implementation // TODO: generic implementation
template <typename T> template <typename T>
T det (vector<T, 2> const & v0, vector<T, 2> const & v1) T det(vector<T, 2> const & v0, vector<T, 2> const & v1)
{ {
return v0[0] * v1[1] - v0[1] * v1[0]; return v0[0] * v1[1] - v0[1] * v1[0];
} }
template <typename T> template <typename T>
T det (vector<T, 3> const & v0, vector<T, 3> const & v1, vector<T, 3> const & v2) T det(vector<T, 3> const & v0, vector<T, 3> const & v1, vector<T, 3> const & v2)
{ {
return return
+ v0[0] * v1[1] * v2[2] + v0[0] * v1[1] * v2[2]
@ -234,7 +234,7 @@ namespace psemek::geom
} }
template <typename T> template <typename T>
vector<T, 3> cross (vector<T, 3> const & v0, vector<T, 3> const & v1) vector<T, 3> cross(vector<T, 3> const & v0, vector<T, 3> const & v1)
{ {
return vector<T, 3>{ return vector<T, 3>{
v0[1] * v1[2] - v0[2] * v1[1], v0[1] * v1[2] - v0[2] * v1[1],
@ -244,13 +244,13 @@ namespace psemek::geom
} }
template <typename T> template <typename T>
T lerp (T const & x0, T const & x1, T const & t) T lerp(T const & x0, T const & x1, T const & t)
{ {
return x0 * (T(1) - t) + x1 * t; return x0 * (T(1) - t) + x1 * t;
} }
template <typename T, std::size_t N> template <typename T, std::size_t N>
vector<T, N> lerp (vector<T, N> const & v0, vector<T, N> const & v1, T const & t) vector<T, N> lerp(vector<T, N> const & v0, vector<T, N> const & v1, T const & t)
{ {
return v0 * (T(1) - t) + v1 * t; return v0 * (T(1) - t) + v1 * t;
} }

View file

@ -12,7 +12,7 @@ namespace psemek::pcg
perlin(util::basic_pixmap<geom::vector<float, 2>> grad_map); perlin(util::basic_pixmap<geom::vector<float, 2>> grad_map);
perlin(perlin &&) = default; perlin(perlin &&) = default;
perlin & operator= (perlin &&) = default; perlin & operator = (perlin &&) = default;
std::size_t width() const std::size_t width() const
{ {
@ -26,7 +26,7 @@ namespace psemek::pcg
// x \in [0.0 .. 1.0] // x \in [0.0 .. 1.0]
// y \in [0.0 .. 1.0] // y \in [0.0 .. 1.0]
float operator() (float x, float y) const; float operator()(float x, float y) const;
private: private:
util::basic_pixmap<geom::vector<float, 2>> grad_map_; util::basic_pixmap<geom::vector<float, 2>> grad_map_;

View file

@ -22,7 +22,7 @@ namespace psemek::pcg
return step(x0, x1, s); return step(x0, x1, s);
} }
float perlin::operator() (float x, float y) const float perlin::operator()(float x, float y) const
{ {
assert(x >= 0.f); assert(x >= 0.f);
assert(y >= 0.f); assert(y >= 0.f);

View file

@ -13,6 +13,6 @@
namespace psemek::util namespace psemek::util
{ {
[[noreturn]] bool assert_handler (char const * expression, char const * file, int line); [[noreturn]] bool assert_handler(char const * expression, char const * file, int line);
} }

View file

@ -20,7 +20,7 @@ namespace psemek::util
blob & operator = (blob const & other); blob & operator = (blob const & other);
blob & operator = (blob && other); blob & operator = (blob && other);
~ blob() = default; ~blob() = default;
char * data() { return data_.get(); } char * data() { return data_.get(); }
char const * data() const { return data_.get(); } char const * data() const { return data_.get(); }
@ -39,8 +39,8 @@ namespace psemek::util
char * end() { return data() + size(); } char * end() { return data() + size(); }
char const * end() const { return data() + size(); } char const * end() const { return data() + size(); }
char & operator[] (std::size_t i) { return data()[i]; } char & operator[](std::size_t i) { return data()[i]; }
char const & operator[] (std::size_t i) const { return data()[i]; } char const & operator[](std::size_t i) const { return data()[i]; }
std::string string() const; std::string string() const;
std::string_view string_view() const; std::string_view string_view() const;

View file

@ -14,17 +14,17 @@ namespace psemek::util
typedef Clock clock_type; typedef Clock clock_type;
typedef typename clock_type::time_point time_point_type; typedef typename clock_type::time_point time_point_type;
clock ( ) clock()
{ {
restart(); restart();
} }
time_point_type now ( ) const time_point_type now() const
{ {
return clock_type::now(); return clock_type::now();
} }
duration_type restart ( ) duration_type restart()
{ {
auto t = now(); auto t = now();
auto delta = t - start_; auto delta = t - start_;
@ -32,12 +32,12 @@ namespace psemek::util
return std::chrono::duration_cast<duration_type>(delta); return std::chrono::duration_cast<duration_type>(delta);
} }
duration_type duration ( ) const duration_type duration() const
{ {
return std::chrono::duration_cast<duration_type>(now() - start_); return std::chrono::duration_cast<duration_type>(now() - start_);
} }
rep_type count ( ) const rep_type count() const
{ {
return duration().count(); return duration().count();
} }

View file

@ -0,0 +1,40 @@
#pragma once
namespace psemek::util
{
namespace detail
{
template <typename T, bool CanInherit>
struct ebo_helper_impl : T
{
T & data() { return *this; }
T const & data() const { return *this; }
template <typename ... Args>
ebo_helper_impl(Args && ... args)
: T(std::forward<Args>(args)...)
{}
};
template <typename T>
struct ebo_helper_impl<T, false>
{
T value;
T & data() { return value; }
T const & data() const { return value; }
template <typename ... Args>
ebo_helper_impl(Args && ... args)
: value(std::forward<Args>(args)...)
{}
};
}
template <typename T>
using ebo_helper = detail::ebo_helper_impl<T, std::is_class_v<T> && !(std::is_final_v<T>)>;
}

View file

@ -0,0 +1,14 @@
#pragma once
namespace psemek::util
{
struct empty{};
template <typename Stream>
Stream & operator << (Stream & os, empty)
{
return os << "empty";
}
}

View file

@ -10,16 +10,16 @@ namespace psemek::util
template <typename T, typename IndexType = std::size_t> template <typename T, typename IndexType = std::size_t>
struct flat_list struct flat_list
{ {
flat_list ( ); flat_list();
explicit flat_list (std::size_t count); explicit flat_list(std::size_t count);
flat_list (std::size_t count, T const & value); flat_list(std::size_t count, T const & value);
flat_list (flat_list const &); flat_list(flat_list const &);
flat_list (flat_list &&); flat_list(flat_list &&);
flat_list (std::initializer_list<T> init); flat_list(std::initializer_list<T> init);
~ flat_list ( ); ~flat_list();
std::size_t size ( ) const; std::size_t size() const;
private: private:
using item = std::aligned_storage_t<std::max(sizeof(T), sizeof(IndexType))>; using item = std::aligned_storage_t<std::max(sizeof(T), sizeof(IndexType))>;
@ -33,22 +33,22 @@ namespace psemek::util
}; };
template <typename T, typename I> template <typename T, typename I>
flat_list<T, I>::flat_list ( ) = default; flat_list<T, I>::flat_list() = default;
template <typename T, typename I> template <typename T, typename I>
flat_list<T, I>::flat_list (std::size_t count) flat_list<T, I>::flat_list(std::size_t count)
: data_(count) : data_(count)
, size_(count) , size_(count)
{ } {}
template <typename T, typename I> template <typename T, typename I>
flat_list<T, I>::flat_list (std::size_t count, T const & value) flat_list<T, I>::flat_list(std::size_t count, T const & value)
: data_(count, value) : data_(count, value)
, size_(count) , size_(count)
{ } {}
template <typename T, typename I> template <typename T, typename I>
flat_list<T, I>::flat_list (flat_list const & other) = default; flat_list<T, I>::flat_list(flat_list const & other) = default;
template <typename T, typename I> template <typename T, typename I>
flat_list<T, I>::flat_list (flat_list && other) flat_list<T, I>::flat_list (flat_list && other)
@ -61,16 +61,16 @@ namespace psemek::util
} }
template <typename T, typename I> template <typename T, typename I>
flat_list<T, I>::flat_list (std::initializer_list<T> init) flat_list<T, I>::flat_list(std::initializer_list<T> init)
: data_(std::move(init)) : data_(std::move(init))
, size_(data_.size()) , size_(data_.size())
{ } {}
template <typename T, typename I> template <typename T, typename I>
flat_list<T, I>::~flat_list ( ) = default; flat_list<T, I>::~flat_list() = default;
template <typename T, typename I> template <typename T, typename I>
std::size_t flat_list<T, I>::size ( ) const std::size_t flat_list<T, I>::size() const
{ {
return size_; return size_;
} }

View file

@ -16,7 +16,7 @@ namespace psemek::util
F f; F f;
template <typename T> template <typename T>
auto operator() (std::optional<T> && x) auto operator()(std::optional<T> && x)
{ {
using R = decltype(f(*x)); using R = decltype(f(*x));
@ -30,7 +30,7 @@ namespace psemek::util
} }
template <typename F> template <typename F>
auto fmap (F f) auto fmap(F f)
{ {
return detail::fmap<F>{std::move(f)}; return detail::fmap<F>{std::move(f)};
} }

View file

@ -8,13 +8,13 @@ namespace psemek::util
constexpr auto id = [](auto && x) -> decltype(auto) { return x; }; constexpr auto id = [](auto && x) -> decltype(auto) { return x; };
template <typename T> template <typename T>
auto constant (T const & x) auto constant(T const & x)
{ {
return [x](auto const & ...){ return x; }; return [x](auto const & ...){ return x; };
} }
template <typename F1, typename F2> template <typename F1, typename F2>
auto bind_and (F1 && f1, F2 && f2) auto bind_and(F1 && f1, F2 && f2)
{ {
return [=](auto const &... args){ return [=](auto const &... args){
return f1(args...) && f2(args...); return f1(args...) && f2(args...);

View file

@ -10,9 +10,9 @@ namespace psemek::util
{ {
Gen generator; Gen generator;
lazy_range (Gen gen) lazy_range(Gen gen)
: generator(std::move(gen)) : generator(std::move(gen))
{ } {}
using value_type = decltype(generator()); using value_type = decltype(generator());
@ -24,21 +24,21 @@ namespace psemek::util
value_type value; value_type value;
value_type const & operator * () value_type const & operator*()
{ {
return value; return value;
} }
iterator & operator ++ () iterator & operator++()
{ {
value = range.generator(); value = range.generator();
return *this; return *this;
} }
}; };
iterator begin ( ) iterator begin()
{ {
return { *this, generator() }; return {*this, generator()};
} }
struct sentinel struct sentinel
@ -46,7 +46,7 @@ namespace psemek::util
using iterator_category = std::input_iterator_tag; using iterator_category = std::input_iterator_tag;
}; };
sentinel end ( ) sentinel end()
{ {
return {}; return {};
} }

View file

@ -14,9 +14,9 @@ namespace psemek::util
template <typename R, typename ... Args> template <typename R, typename ... Args>
struct movable_function_node_base<R(Args...)> struct movable_function_node_base<R(Args...)>
{ {
virtual R call (Args ...) = 0; virtual R call(Args ...) = 0;
virtual ~ movable_function_node_base ( ) = default; virtual ~movable_function_node_base() = default;
}; };
template <typename Signature, typename F> template <typename Signature, typename F>
@ -28,18 +28,18 @@ namespace psemek::util
{ {
F f; F f;
movable_function_node (F && f) movable_function_node(F && f)
: f(std::move(f)) : f(std::move(f))
{ } {}
R call (Args ... args) override R call(Args ... args) override
{ {
return f(args...); return f(args...);
} }
}; };
// Implemented in cpp to prevent dependency on <functional> // Implemented in cpp to prevent dependency on <functional>
[[noreturn]] void bad_function_call ( ); [[noreturn]] void bad_function_call();
} }
@ -51,12 +51,12 @@ namespace psemek::util
{ {
using signature = R(Args...); using signature = R(Args...);
movable_function ( ) = default; movable_function() = default;
template <typename F> template <typename F>
movable_function (F f) movable_function(F f)
: p { std::make_unique<detail::movable_function_node<signature, std::remove_cv_t<F>>>(std::move(f)) } : p {std::make_unique<detail::movable_function_node<signature, std::remove_cv_t<F>>>(std::move(f))}
{ } {}
movable_function (movable_function &&) = default; movable_function (movable_function &&) = default;
movable_function & operator = (movable_function &&) = default; movable_function & operator = (movable_function &&) = default;
@ -64,12 +64,12 @@ namespace psemek::util
movable_function (movable_function const &) = delete; movable_function (movable_function const &) = delete;
movable_function & operator = (movable_function const &) = delete; movable_function & operator = (movable_function const &) = delete;
explicit operator bool ( ) const explicit operator bool() const
{ {
return static_cast<bool>(p); return static_cast<bool>(p);
} }
R operator() (Args ... args) const R operator()(Args ... args) const
{ {
if (!p) if (!p)
detail::bad_function_call(); detail::bad_function_call();

View file

@ -8,21 +8,21 @@ namespace psemek::util
template <typename T> template <typename T>
struct moving_average struct moving_average
{ {
moving_average (std::size_t max) moving_average(std::size_t max)
: data_(max, T()) : data_(max, T())
, begin_(0) , begin_(0)
, size_(0) , size_(0)
, sum_(T()) , sum_(T())
{ } {}
void clear ( ) void clear()
{ {
begin_ = 0; begin_ = 0;
size_ = 0; size_ = 0;
sum_ = T(0); sum_ = T(0);
} }
void push (T x) void push(T x)
{ {
if (size_ >= data_.size()) if (size_ >= data_.size())
{ {
@ -38,17 +38,17 @@ namespace psemek::util
begin_ = 0; begin_ = 0;
} }
T sum ( ) const T sum() const
{ {
return sum_; return sum_;
} }
std::size_t count ( ) const std::size_t count() const
{ {
return size_; return size_;
} }
T average ( ) const T average() const
{ {
return sum() / count(); return sum() / count();
} }

View file

@ -1,16 +0,0 @@
#pragma once
namespace psemek::util
{
struct noncopyable
{
noncopyable (noncopyable const &) = delete;
noncopyable & operator = (noncopyable const &) = delete;
noncopyable ( ) = default;
noncopyable (noncopyable &&) = default;
noncopyable & operator = (noncopyable &&) = default;
};
}

View file

@ -3,6 +3,6 @@
namespace psemek::util namespace psemek::util
{ {
void not_implemented ( ); void not_implemented();
} }

View file

@ -12,9 +12,9 @@ namespace psemek::util
struct overload_impl struct overload_impl
: Fs... : Fs...
{ {
overload_impl (Fs ... fs) overload_impl(Fs ... fs)
: Fs(fs)... : Fs(fs)...
{ } {}
using Fs::operator()...; using Fs::operator()...;
}; };
@ -22,7 +22,7 @@ namespace psemek::util
} }
template <typename ... Fs> template <typename ... Fs>
auto overload (Fs ... fs) auto overload(Fs ... fs)
{ {
return detail::overload_impl<Fs...>{std::move(fs)...}; return detail::overload_impl<Fs...>{std::move(fs)...};
} }

View file

@ -14,22 +14,22 @@ namespace psemek::util::pimpl
{ {
protected: protected:
using impl_type = ::util::pimpl::impl<Parent>; using impl_type = pimpl::impl<Parent>;
impl_type * pimpl ( ) { return reinterpret_cast<impl_type *>(std::addressof(storage_)); } impl_type * pimpl() { return reinterpret_cast<impl_type *>(std::addressof(storage_)); }
impl_type & impl ( ) { return *pimpl(); } impl_type & impl() { return *pimpl(); }
impl_type const * pimpl ( ) const { return reinterpret_cast<impl_type const *>(std::addressof(storage_)); } impl_type const * pimpl() const { return reinterpret_cast<impl_type const *>(std::addressof(storage_)); }
impl_type const & impl ( ) const { return *pimpl(); } impl_type const & impl() const { return *pimpl(); }
template <typename ... Args> template <typename ... Args>
in_place (Args && ... args) in_place(Args && ... args)
{ {
static_assert(sizeof(impl_type) <= Size, "impl storage size too small"); static_assert(sizeof(impl_type) <= Size, "impl storage size too small");
new (pimpl()) impl_type (std::forward<Args>(args)...); new (pimpl()) impl_type (std::forward<Args>(args)...);
} }
~ in_place ( ) ~in_place()
{ {
impl().~impl_type(); impl().~impl_type();
} }
@ -44,21 +44,21 @@ namespace psemek::util::pimpl
{ {
protected: protected:
using impl_type = ::util::pimpl::impl<Parent>; using impl_type = pimpl::impl<Parent>;
impl_type * pimpl ( ) { return pointer_.get(); } impl_type * pimpl() { return pointer_.get(); }
impl_type & impl ( ) { return *pimpl(); } impl_type & impl() { return *pimpl(); }
impl_type const * pimpl ( ) const { return pointer_.get(); } impl_type const * pimpl() const { return pointer_.get(); }
impl_type const & impl ( ) const { return *pimpl(); } impl_type const & impl() const { return *pimpl(); }
template <typename ... Args> template <typename ... Args>
dynamic (Args && ... args) dynamic(Args && ... args)
{ {
pointer_.reset(new impl_type(std::forward<Args>(args)...)); pointer_.reset(new impl_type(std::forward<Args>(args)...));
} }
~ dynamic ( ) = default; ~dynamic() = default;
private: private:

View file

@ -28,8 +28,8 @@ namespace psemek::util
void resize(std::size_t width, std::size_t height); void resize(std::size_t width, std::size_t height);
void resize(std::size_t width, std::size_t height, Pixel value); void resize(std::size_t width, std::size_t height, Pixel value);
Pixel * operator[] (std::size_t row); Pixel * operator[](std::size_t row);
Pixel const * operator[] (std::size_t row) const; Pixel const * operator[](std::size_t row) const;
Pixel * data() { return data_.get(); } Pixel * data() { return data_.get(); }
Pixel const * data() const { return data_.get(); } Pixel const * data() const { return data_.get(); }
@ -124,13 +124,13 @@ namespace psemek::util
} }
template <typename Pixel> template <typename Pixel>
Pixel * basic_pixmap<Pixel>::operator[] (std::size_t row) Pixel * basic_pixmap<Pixel>::operator[](std::size_t row)
{ {
return data() + row * width(); return data() + row * width();
} }
template <typename Pixel> template <typename Pixel>
Pixel const * basic_pixmap<Pixel>::operator[] (std::size_t row) const Pixel const * basic_pixmap<Pixel>::operator[](std::size_t row) const
{ {
return data() + row * width(); return data() + row * width();
} }

View file

@ -16,7 +16,7 @@ namespace psemek::util
UpTo up_to; UpTo up_to;
}; };
void pretty_print_time (std::ostream & o, std::int64_t d, std::int64_t up_to); void pretty_print_time(std::ostream & o, std::int64_t d, std::int64_t up_to);
template <typename Duration, typename UpTo> template <typename Duration, typename UpTo>
std::ostream & operator << (std::ostream & o, pretty_print_time_wrapper<Duration, UpTo> t) std::ostream & operator << (std::ostream & o, pretty_print_time_wrapper<Duration, UpTo> t)
@ -30,13 +30,13 @@ namespace psemek::util
} }
template <typename Rep, typename Period, typename UpTo> template <typename Rep, typename Period, typename UpTo>
auto pretty (std::chrono::duration<Rep, Period> d, UpTo up_to) auto pretty(std::chrono::duration<Rep, Period> d, UpTo up_to)
{ {
return detail::pretty_print_time_wrapper<std::chrono::duration<Rep, Period>, UpTo>{d, up_to}; return detail::pretty_print_time_wrapper<std::chrono::duration<Rep, Period>, UpTo>{d, up_to};
} }
template <typename Rep, typename Period> template <typename Rep, typename Period>
auto pretty (std::chrono::duration<Rep, Period> d) auto pretty(std::chrono::duration<Rep, Period> d)
{ {
return pretty(d, std::chrono::seconds{1}); return pretty(d, std::chrono::seconds{1});
} }

View file

@ -10,11 +10,11 @@ namespace psemek::util
struct profiler struct profiler
{ {
profiler (std::string name) profiler(std::string name)
: name_(std::move(name)) : name_(std::move(name))
{ } {}
~ profiler ( ) ~ profiler()
{ {
std::cout << name_ << ": " << util::pretty(clock_.duration(), std::chrono::microseconds{1}) << "\n"; std::cout << name_ << ": " << util::pretty(clock_.duration(), std::chrono::microseconds{1}) << "\n";
} }

View file

@ -10,14 +10,14 @@ namespace psemek::util
{ {
template <typename Container> template <typename Container>
auto begin_helper (Container & x) auto begin_helper(Container & x)
{ {
using std::begin; using std::begin;
return begin(x); return begin(x);
} }
template <typename Container> template <typename Container>
auto end_helper (Container & x) auto end_helper(Container & x)
{ {
using std::end; using std::end;
return end(x); return end(x);
@ -26,13 +26,13 @@ namespace psemek::util
} }
template <typename Container> template <typename Container>
auto begin (Container & x) auto begin(Container & x)
{ {
return detail::begin_helper(x); return detail::begin_helper(x);
} }
template <typename Container> template <typename Container>
auto end (Container & x) auto end(Container & x)
{ {
return detail::end_helper(x); return detail::end_helper(x);
} }
@ -68,13 +68,13 @@ namespace psemek::util
}; };
template <typename Range> template <typename Range>
auto reversed (Range const & r) auto reversed(Range const & r)
{ {
auto it1 = begin(r); auto it1 = begin(r);
auto it2 = end(r); auto it2 = end(r);
using ReverseIterator = std::reverse_iterator<decltype(it1)>; using ReverseIterator = std::reverse_iterator<decltype(it1)>;
return range<ReverseIterator>{ std::make_reverse_iterator(it2), std::make_reverse_iterator(it1) }; return range<ReverseIterator>{std::make_reverse_iterator(it2), std::make_reverse_iterator(it1)};
} }
} }

View file

@ -12,7 +12,7 @@ namespace psemek::util
F f; F f;
template <typename ... Args> template <typename ... Args>
auto operator() (Args && ... args) -> decltype(auto) auto operator()(Args && ... args) -> decltype(auto)
{ {
return f(*this, std::forward<Args>(args)...); return f(*this, std::forward<Args>(args)...);
} }
@ -21,7 +21,7 @@ namespace psemek::util
} }
template <typename F> template <typename F>
auto recursive (F f) auto recursive(F f)
{ {
return detail::recursive_impl<F>{std::move(f)}; return detail::recursive_impl<F>{std::move(f)};
} }

View file

@ -42,8 +42,8 @@ namespace psemek::util
char * end() { return data() + size(); } char * end() { return data() + size(); }
char const * end() const { return data() + size(); } char const * end() const { return data() + size(); }
char & operator[] (std::size_t i) { return data()[i]; } char & operator[](std::size_t i) { return data()[i]; }
char const & operator[] (std::size_t i) const { return data()[i]; } char const & operator[](std::size_t i) const { return data()[i]; }
std::string string() const; std::string string() const;
std::string_view string_view() const; std::string_view string_view() const;
@ -83,7 +83,7 @@ namespace psemek::util
, size_{size} , size_{size}
{} {}
inline shared_blob & shared_blob::operator=(shared_blob const & other) inline shared_blob & shared_blob::operator = (shared_blob const & other)
{ {
if (this != &other) if (this != &other)
{ {
@ -93,7 +93,7 @@ namespace psemek::util
return *this; return *this;
} }
inline shared_blob & shared_blob::operator=(shared_blob && other) inline shared_blob & shared_blob::operator = (shared_blob && other)
{ {
if (this != &other) if (this != &other)
{ {
@ -104,7 +104,7 @@ namespace psemek::util
return *this; return *this;
} }
inline shared_blob & shared_blob::operator=(blob && other) inline shared_blob & shared_blob::operator = (blob && other)
{ {
size_ = other.size(); size_ = other.size();
data_ = other.release(); data_ = other.release();

View file

@ -13,32 +13,32 @@ namespace psemek::util
template <typename T> template <typename T>
struct synchronized_queue struct synchronized_queue
{ {
synchronized_queue (std::size_t max_size = std::numeric_limits<std::size_t>::max()) noexcept synchronized_queue(std::size_t max_size = std::numeric_limits<std::size_t>::max()) noexcept
: max_size_(max_size) : max_size_(max_size)
{ } {}
std::size_t max_size ( ) const noexcept std::size_t max_size() const noexcept
{ {
return max_size_; return max_size_;
} }
void push (T const & x); void push(T const & x);
void push (T && x); void push(T && x);
T pop ( ); T pop();
bool try_push (T const & x); bool try_push(T const & x);
template <typename Rep, typename Period> template <typename Rep, typename Period>
bool try_push (T const & x, std::chrono::duration<Rep, Period> const & timeout); bool try_push(T const & x, std::chrono::duration<Rep, Period> const & timeout);
std::optional<T> try_pop ( ); std::optional<T> try_pop();
template <typename Rep, typename Period> template <typename Rep, typename Period>
std::optional<T> try_pop (std::chrono::duration<Rep, Period> const & timeout); std::optional<T> try_pop(std::chrono::duration<Rep, Period> const & timeout);
void clear ( ); void clear();
// Wait for the queue to become empty // Wait for the queue to become empty
// e.g. when no new items are going to be pushed // e.g. when no new items are going to be pushed
void wait ( ); void wait();
private: private:
std::mutex mutex; std::mutex mutex;
@ -48,9 +48,9 @@ namespace psemek::util
}; };
template <typename T> template <typename T>
void synchronized_queue<T>::push (T const & x) void synchronized_queue<T>::push(T const & x)
{ {
std::unique_lock lock { mutex }; std::unique_lock lock{mutex};
push_cv.wait(lock, [this]{ return queue.size() < max_size(); }); push_cv.wait(lock, [this]{ return queue.size() < max_size(); });
queue.push_back(x); queue.push_back(x);
pop_cv.notify_one(); pop_cv.notify_one();
@ -59,16 +59,16 @@ namespace psemek::util
template <typename T> template <typename T>
void synchronized_queue<T>::push (T && x) void synchronized_queue<T>::push (T && x)
{ {
std::unique_lock lock { mutex }; std::unique_lock lock{mutex};
push_cv.wait(lock, [this]{ return queue.size() < max_size(); }); push_cv.wait(lock, [this]{ return queue.size() < max_size(); });
queue.push_back(std::move(x)); queue.push_back(std::move(x));
pop_cv.notify_one(); pop_cv.notify_one();
} }
template <typename T> template <typename T>
T synchronized_queue<T>::pop ( ) T synchronized_queue<T>::pop()
{ {
std::unique_lock lock { mutex }; std::unique_lock lock{mutex};
pop_cv.wait(lock, [this]{ return !queue.empty(); }); pop_cv.wait(lock, [this]{ return !queue.empty(); });
T x = std::move(queue.front()); T x = std::move(queue.front());
queue.pop_front(); queue.pop_front();
@ -77,10 +77,10 @@ namespace psemek::util
} }
template <typename T> template <typename T>
bool synchronized_queue<T>::try_push (T const & x) bool synchronized_queue<T>::try_push(T const & x)
{ {
std::lock_guard lock { mutex }; std::lock_guard lock{mutex};
if (queue.size() >= max_size()) if (queue.size() >= max_size())
return false; return false;
queue.push_back(x); queue.push_back(x);
@ -90,10 +90,10 @@ namespace psemek::util
template <typename T> template <typename T>
template <typename Rep, typename Period> template <typename Rep, typename Period>
bool synchronized_queue<T>::try_push (T const & x, std::chrono::duration<Rep, Period> const & timeout) bool synchronized_queue<T>::try_push(T const & x, std::chrono::duration<Rep, Period> const & timeout)
{ {
std::unique_lock lock { mutex }; std::unique_lock lock{mutex};
if (push_cv.wait_for(lock, timeout, [this]{ return queue.size() < max_size(); })) if (push_cv.wait_for(lock, timeout, [this]{ return queue.size() < max_size(); }))
{ {
queue.push_back(std::move(x)); queue.push_back(std::move(x));
pop_cv.notify_one(); pop_cv.notify_one();
@ -103,9 +103,9 @@ namespace psemek::util
} }
template <typename T> template <typename T>
std::optional<T> synchronized_queue<T>::try_pop ( ) std::optional<T> synchronized_queue<T>::try_pop()
{ {
std::lock_guard lock { mutex }; std::lock_guard lock{mutex};
if (queue.empty()) if (queue.empty())
return std::nullopt; return std::nullopt;
T x = std::move(queue.front()); T x = std::move(queue.front());
@ -116,31 +116,31 @@ namespace psemek::util
template <typename T> template <typename T>
template <typename Rep, typename Period> template <typename Rep, typename Period>
std::optional<T> synchronized_queue<T>::try_pop (std::chrono::duration<Rep, Period> const & timeout) std::optional<T> synchronized_queue<T>::try_pop(std::chrono::duration<Rep, Period> const & timeout)
{ {
std::unique_lock lock { mutex }; std::unique_lock lock{mutex};
if (pop_cv.wait_for(lock, timeout, [this]{ return !queue.empty(); })) if (pop_cv.wait_for(lock, timeout, [this]{ return !queue.empty(); }))
{ {
T x = std::move(queue.front()); T x = std::move(queue.front());
queue.pop_front(); queue.pop_front();
push_cv.notify_one(); push_cv.notify_one();
return { std::move(x) }; return {std::move(x)};
} }
return std::nullopt; return std::nullopt;
} }
template <typename T> template <typename T>
void synchronized_queue<T>::clear ( ) void synchronized_queue<T>::clear()
{ {
std::lock_guard lock { mutex }; std::lock_guard lock{mutex};
queue.clear(); queue.clear();
push_cv.notify_all(); push_cv.notify_all();
} }
template <typename T> template <typename T>
void synchronized_queue<T>::wait ( ) void synchronized_queue<T>::wait()
{ {
std::unique_lock lock { mutex }; std::unique_lock lock{mutex};
push_cv.wait(lock, [this]{ return queue.empty(); }); push_cv.wait(lock, [this]{ return queue.empty(); });
} }

View file

@ -9,13 +9,13 @@ namespace psemek::util
: std::thread : std::thread
{ {
template <typename ... Args> template <typename ... Args>
thread (Args && ... args) thread(Args && ... args)
: std::thread(std::forward<Args>(args)...) : std::thread(std::forward<Args>(args)...)
{ } {}
thread (thread &&) = default; thread(thread &&) = default;
~ thread ( ) ~ thread()
{ {
if (joinable()) if (joinable())
join(); join();

View file

@ -12,26 +12,26 @@ namespace psemek::util
struct threadpool struct threadpool
{ {
threadpool ( ) threadpool()
: threadpool(std::max(1u, std::thread::hardware_concurrency())) : threadpool(std::max(1u, std::thread::hardware_concurrency()))
{ } {}
threadpool (std::size_t thread_count) threadpool(std::size_t thread_count)
{ {
start(thread_count); start(thread_count);
} }
~ threadpool ( ) ~ threadpool()
{ {
stop(); stop();
} }
template <typename F> template <typename F>
auto dispatch (F && f) auto dispatch(F && f)
{ {
using R = decltype(f()); using R = decltype(f());
std::packaged_task<R()> task { std::forward<F>(f) }; std::packaged_task<R()> task{std::forward<F>(f)};
auto result = task.get_future(); auto result = task.get_future();
@ -40,11 +40,11 @@ namespace psemek::util
return result; return result;
} }
void start (std::size_t thread_count); void start(std::size_t thread_count);
void stop ( ); void stop();
void wait ( ) void wait()
{ {
tasks_queue.wait(); tasks_queue.wait();
} }

View file

@ -9,11 +9,11 @@ namespace psemek::util
struct timer struct timer
: clock<Duration, Clock> : clock<Duration, Clock>
{ {
timer (Duration duration) timer(Duration duration)
: duration_(duration) : duration_(duration)
{ } {}
explicit operator bool ( ) explicit operator bool()
{ {
if (this->duration() >= duration_) if (this->duration() >= duration_)
{ {

View file

@ -10,7 +10,7 @@ namespace psemek::util
{ {
template <typename Char, typename Traits = std::char_traits<Char>, typename ... Args> template <typename Char, typename Traits = std::char_traits<Char>, typename ... Args>
std::basic_string<Char, Traits> to_string (Args const & ... args) std::basic_string<Char, Traits> to_string(Args const & ... args)
{ {
std::basic_ostringstream<Char, Traits> oss; std::basic_ostringstream<Char, Traits> oss;
@ -22,25 +22,25 @@ namespace psemek::util
} }
template <typename ... Args> template <typename ... Args>
std::string to_string (Args const & ... args) std::string to_string(Args const & ... args)
{ {
return detail::to_string<char>(args...); return detail::to_string<char>(args...);
} }
template <typename ... Args> template <typename ... Args>
std::wstring to_wstring (Args const & ... args) std::wstring to_wstring(Args const & ... args)
{ {
return detail::to_string<wchar_t>(args...); return detail::to_string<wchar_t>(args...);
} }
template <typename ... Args> template <typename ... Args>
std::u32string to_u32string (Args const & ... args) std::u32string to_u32string(Args const & ... args)
{ {
return detail::to_string<char32_t>(args...); return detail::to_string<char32_t>(args...);
} }
template <typename T, typename Char, typename Traits> template <typename T, typename Char, typename Traits>
T from_string (std::basic_string<Char, Traits> const & s) T from_string(std::basic_string<Char, Traits> const & s)
{ {
std::basic_istringstream<Char, Traits> iss(s); std::basic_istringstream<Char, Traits> iss(s);
T x; T x;
@ -51,7 +51,7 @@ namespace psemek::util
} }
template <typename T, typename Char> template <typename T, typename Char>
T from_string (Char const * s) T from_string(Char const * s)
{ {
return from_string<T, Char, std::char_traits<Char>>(s); return from_string<T, Char, std::char_traits<Char>>(s);
} }

View file

@ -5,7 +5,7 @@
namespace psemek::util namespace psemek::util
{ {
std::string to_utf8 (std::u32string const & str); std::string to_utf8(std::u32string const & str);
std::u32string from_utf8 (std::string const & str); std::u32string from_utf8(std::string const & str);
} }

View file

@ -6,7 +6,7 @@
namespace psemek::util namespace psemek::util
{ {
[[noreturn]] bool assert_handler (char const * expression, char const * file, int line) [[noreturn]] bool assert_handler(char const * expression, char const * file, int line)
{ {
throw std::runtime_error(to_string(file, ":", line, " Assertion failed: ", expression)); throw std::runtime_error(to_string(file, ":", line, " Assertion failed: ", expression));
} }

View file

@ -8,9 +8,9 @@ namespace psemek::util
namespace detail namespace detail
{ {
void bad_function_call ( ) void bad_function_call()
{ {
throw std::bad_function_call(); throw std::bad_function_call{};
} }
} }

View file

@ -5,7 +5,7 @@
namespace psemek::util namespace psemek::util
{ {
void not_implemented ( ) void not_implemented()
{ {
throw std::runtime_error("Not implemented"); throw std::runtime_error("Not implemented");
} }

View file

@ -6,7 +6,7 @@ namespace psemek::util
namespace detail namespace detail
{ {
void pretty_print_time (std::ostream & o, std::int64_t d, std::int64_t up_to) void pretty_print_time(std::ostream & o, std::int64_t d, std::int64_t up_to)
{ {
static constexpr const std::int64_t durations[8] = { static constexpr const std::int64_t durations[8] = {
604800 * 1000000000ull, 604800 * 1000000000ull,

View file

@ -3,7 +3,7 @@
namespace psemek::util namespace psemek::util
{ {
void threadpool::start (std::size_t thread_count) void threadpool::start(std::size_t thread_count)
{ {
for (std::size_t th = 0; th < thread_count; ++th) for (std::size_t th = 0; th < thread_count; ++th)
{ {
@ -22,7 +22,7 @@ namespace psemek::util
} }
} }
void threadpool::stop ( ) void threadpool::stop()
{ {
tasks_queue.clear(); tasks_queue.clear();
for (auto const & thread: threads) for (auto const & thread: threads)

View file

@ -8,14 +8,14 @@ namespace psemek::util
using converter = std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t>; using converter = std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t>;
std::string to_utf8 (std::u32string const & str) std::string to_utf8(std::u32string const & str)
{ {
return converter().to_bytes(str); return converter{}.to_bytes(str);
} }
std::u32string from_utf8 (std::string const & str) std::u32string from_utf8(std::string const & str)
{ {
return converter().from_bytes(str); return converter{}.from_bytes(str);
} }
} }

View file

@ -1,4 +1,3 @@
* Use the same code style everywhere (mostly about spaces after function names)
* Make sure program & shaders are deleted properly if program creation fails * Make sure program & shaders are deleted properly if program creation fails
* Remove gfx::vertex, setup mesh using attributes directly * Remove gfx::vertex, setup mesh using attributes directly
* Design affine transforms in geom & use them instead of matrices when appropriate * Design affine transforms in geom & use them instead of matrices when appropriate