Uniformize code style & do a few code rearrangements
This commit is contained in:
parent
a2b1d90c48
commit
6225f89f88
69 changed files with 460 additions and 481 deletions
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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)>;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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]);
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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>)>;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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_;
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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];
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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};
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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];
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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_;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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_;
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
40
libs/util/include/psemek/util/ebo.hpp
Normal file
40
libs/util/include/psemek/util/ebo.hpp
Normal 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>)>;
|
||||||
|
|
||||||
|
}
|
||||||
14
libs/util/include/psemek/util/empty.hpp
Normal file
14
libs/util/include/psemek/util/empty.hpp
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace psemek::util
|
||||||
|
{
|
||||||
|
|
||||||
|
struct empty{};
|
||||||
|
|
||||||
|
template <typename Stream>
|
||||||
|
Stream & operator << (Stream & os, empty)
|
||||||
|
{
|
||||||
|
return os << "empty";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -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_;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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)};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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...);
|
||||||
|
|
|
||||||
|
|
@ -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 {};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -3,6 +3,6 @@
|
||||||
namespace psemek::util
|
namespace psemek::util
|
||||||
{
|
{
|
||||||
|
|
||||||
void not_implemented ( );
|
void not_implemented();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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)...};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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";
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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)};
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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)};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
|
|
||||||
|
|
@ -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(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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_)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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{};
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
1
todo.md
1
todo.md
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue