Uniformize code style & do a few code rearrangements

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

View file

@ -1,6 +1,6 @@
file(GLOB_RECURSE PSEMEK_CG_HEADERS "include/*.hpp")
add_library(cg STATIC ${PSEMEK_CG_HEADERS})
add_library(cg ${PSEMEK_CG_HEADERS})
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)

View file

@ -2,7 +2,7 @@
#include <psemek/geom/box.hpp>
namespace cg
namespace psemek::cg
{
template <typename Iterator>
@ -10,7 +10,7 @@ namespace cg
{
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)
result |= *begin;
return result;

View file

@ -1,15 +1,15 @@
#pragma once
#include <psemek/cg/dcel.hpp>
#include <psemek/geom/vector.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
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);

View file

@ -6,7 +6,7 @@
#include <numeric>
#include <vector>
namespace cg
namespace psemek::cg
{
template <typename InIterator, typename OutIterator>
@ -25,7 +25,7 @@ namespace cg
// find lower half of the hull
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.push_back(*it);
@ -37,7 +37,7 @@ namespace cg
if (*it == *(hull.end() - 2))
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.push_back(*it);

View file

@ -6,7 +6,7 @@
#include <numeric>
#include <vector>
namespace cg
namespace psemek::cg
{
template <typename InIterator, typename OutIterator>
@ -27,9 +27,9 @@ namespace cg
auto o = orientation(*its.front(), *i1, *i2);
// carefully deal with parallel points
if (o == sign_t::positive)
if (o == geom::sign_t::positive)
return true;
else if (o == sign_t::negative)
else if (o == geom::sign_t::negative)
return false;
return *i1 < *i2;
@ -41,7 +41,7 @@ namespace cg
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++ = *it;

View file

@ -2,7 +2,7 @@
#include <psemek/geom/orientation.hpp>
namespace cg
namespace psemek::cg
{
template <typename InIterator, typename OutIterator>
@ -26,7 +26,7 @@ namespace cg
if (jt == it) 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;
break;

View file

@ -6,7 +6,7 @@
#include <numeric>
#include <vector>
namespace cg
namespace psemek::cg
{
namespace detail
@ -21,11 +21,11 @@ namespace cg
// find point in [begin, end) furthest from segment (p1,p2)
auto mid = *std::max_element(begin, end, [&](auto it1, auto it2){
// 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 end2 = std::partition(end1, end, [&](auto it){ return orientation(*mid, *it, *p2) == 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) == geom::sign_t::positive; });
out = quick_hull_recursive_helper(p1, mid, begin, end1, out);
out = quick_hull_recursive_helper(mid, p2, end1, end2, out);
@ -52,7 +52,7 @@ namespace cg
{
auto p = std::find_if(its.begin() + 1, its.end(), [&](auto it){
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);

View file

@ -1,12 +1,13 @@
#pragma once
#include <psemek/cg/utility.hpp>
#include <psemek/util/empty.hpp>
#include <psemek/util/ebo.hpp>
#include <cstddef>
#include <vector>
#include <cassert>
namespace cg
namespace psemek::cg
{
namespace detail

View file

@ -2,7 +2,7 @@
#include <psemek/cg/dcel.hpp>
namespace cg
namespace psemek::cg
{
template <typename Point, typename Edge, typename Face, typename Index>

View file

@ -1,7 +1,6 @@
#pragma once
#include <psemek/geom/intersection.hpp>
#include <psemek/cg/utility.hpp>
#include <cstddef>
#include <algorithm>
@ -11,7 +10,7 @@
#include <deque>
#include <set>
namespace cg
namespace psemek::cg
{
template <typename InIterator, typename OutIterator>

View file

@ -5,7 +5,7 @@
#include <queue>
namespace cg
namespace psemek::cg
{
template <typename Index = std::size_t, typename InputIterator>
@ -58,7 +58,7 @@ namespace cg
auto p3 = e.twin().next().next().origin();
// 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 f1 = twin.face();

View file

@ -1,13 +1,13 @@
#pragma once
#include <psemek/util/functional.hpp>
#include <psemek/geom/orientation.hpp>
#include <psemek/cg/dcel.hpp>
#include <psemek/cg/utility.hpp>
#include <algorithm>
#include <numeric>
namespace cg
namespace psemek::cg
{
namespace detail
@ -93,7 +93,7 @@ namespace cg
bool degenerate = false;
// 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();
if (cur_hull_edge == hull_start)
@ -192,7 +192,7 @@ namespace cg
}
// 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

View file

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

View file

@ -1,11 +1,11 @@
#pragma once
#include <psemek/geom/gauss.hpp>
#include <psemek/cg/triangulation/delaunay.hpp>
#include <psemek/cg/dual.hpp>
#include <psemek/geom/gauss.hpp>
#include <psemek/cg/bbox.hpp>
namespace cg
namespace psemek::cg
{
// Point #0 of the resulting dcel corresponds to the outer face,
@ -35,8 +35,8 @@ namespace cg
using T = typename point_type::scalar_type;
matrix<T, 3, 3> m;
vector<T, 3> b;
geom::matrix<T, 3, 3> m;
geom::vector<T, 3> b;
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];
}
gauss(m, b);
geom::gauss(m, b);
auto newp = result.push_point(point_type{b[0] / 2, b[1] / 2});
newp.edge(result.edge(p.edge().index()));

View file

@ -4,6 +4,6 @@ find_package(GMP REQUIRED)
file(GLOB_RECURSE PSEMEK_GEOM_HEADERS "include/*.hpp")
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_link_libraries(geom PUBLIC Boost::boost GMP)
target_link_libraries(geom PUBLIC util Boost::boost GMP)

View file

@ -15,7 +15,8 @@ namespace psemek::geom
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)
{
auto proj = [](point<T, 2> const & p){
auto proj = [](point<T, 2> const & p)
{
auto const x = p[0];
auto const y = p[1];
return point<T, 3>{ x, y, x*x + y*y };

View file

@ -1,5 +1,7 @@
#pragma once
#include <psemek/util/empty.hpp>
#include <psemek/geom/simplex.hpp>
#include <psemek/geom/orientation.hpp>
#include <psemek/geom/contains.hpp>
@ -10,15 +12,6 @@
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>>
bool intersect(segment<Point> const & s0, segment<Point> const & s1)
{
@ -32,7 +25,7 @@ namespace psemek::geom
// TODO: robust implementation
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 a1 = det(s0[1] - s0[0], s1[0] - s0[0]);
@ -46,7 +39,7 @@ namespace psemek::geom
auto const t1 = a1 / b;
if (t0 < 0 || t0 > 1 || t1 < 0 || t1 > 1)
return empty{};
return util::empty{};
return s0[0] + t0 * (s0[1] - s0[0]);
}
@ -57,7 +50,7 @@ namespace psemek::geom
if (a0 != 0)
{
// 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)
@ -74,7 +67,7 @@ namespace psemek::geom
auto const r1 = std::min(s0[1][k], s1[1][k]);
if (r0 > r1)
return empty{};
return util::empty{};
bool const s0_is_first = s0[0][k] < s1[0][k];

View file

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

View file

@ -10,9 +10,9 @@ namespace psemek::geom
template <typename T, std::size_t D>
struct swap
{
using vector_type = vector<T, D>;
using point_type = point<T, D>;
using matrix_type = matrix<T, D, D>;
using vector_type = geom::vector<T, D>;
using point_type = geom::point<T, D>;
using matrix_type = geom::matrix<T, D, D>;
swap(std::size_t i, std::size_t j);

View file

@ -10,9 +10,9 @@ namespace psemek::geom
template <typename T, std::size_t D>
struct scale
{
using vector_type = vector<T, D>;
using point_type = point<T, D>;
using matrix_type = matrix<T, D, D>;
using vector_type = geom::vector<T, D>;
using point_type = geom::point<T, D>;
using matrix_type = geom::matrix<T, D, D>;
scale();
scale(T v);

View file

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

View file

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

View file

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

View file

@ -14,7 +14,7 @@ namespace psemek::util::pimpl
{
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 & impl() { return *pimpl(); }
@ -44,7 +44,7 @@ namespace psemek::util::pimpl
{
protected:
using impl_type = ::util::pimpl::impl<Parent>;
using impl_type = pimpl::impl<Parent>;
impl_type * pimpl() { return pointer_.get(); }
impl_type & impl() { return *pimpl(); }

View file

@ -10,7 +10,7 @@ namespace psemek::util
void bad_function_call()
{
throw std::bad_function_call();
throw std::bad_function_call{};
}
}

View file

@ -10,12 +10,12 @@ namespace psemek::util
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)
{
return converter().from_bytes(str);
return converter{}.from_bytes(str);
}
}

View file

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