summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/collections.h73
-rw-r--r--lib/geometricPlane.h10
-rw-r--r--lib/maths.cpp7
-rw-r--r--lib/maths.h51
-rw-r--r--lib/persistence.h65
-rw-r--r--lib/ray.h16
-rw-r--r--lib/stream_support.h16
7 files changed, 187 insertions, 51 deletions
diff --git a/lib/collections.h b/lib/collections.h
index 943b986..dd603be 100644
--- a/lib/collections.h
+++ b/lib/collections.h
@@ -2,6 +2,7 @@
#include <algorithm>
#include <array>
+#include <cstdint>
#include <span>
#include <utility>
#include <vector>
@@ -129,18 +130,25 @@ vectorOfN(std::integral auto N, T start = {}, T step = 1)
return v;
}
+template<template<typename...> typename Rtn = std::vector, typename In>
+[[nodiscard]] auto
+materializeRange(const In begin, const In end)
+{
+ return Rtn(begin, end);
+}
+
template<template<typename...> typename Rtn = std::vector, IterableCollection In>
[[nodiscard]] auto
-materializeRange(In && in)
+materializeRange(const In & in)
{
- return Rtn(in.begin(), in.end());
+ return materializeRange<Rtn>(in.begin(), in.end());
}
template<template<typename...> typename Rtn = std::vector, typename In>
[[nodiscard]] auto
materializeRange(const std::pair<In, In> & in)
{
- return Rtn(in.first, in.second);
+ return materializeRange<Rtn>(in.first, in.second);
}
template<typename T> struct pair_range {
@@ -160,3 +168,62 @@ template<typename T> struct pair_range {
};
template<typename T> pair_range(std::pair<T, T>) -> pair_range<T>;
+
+template<typename iter> struct stripiter {
+ [[nodiscard]] constexpr bool
+ operator!=(const stripiter & other) const
+ {
+ return current != other.current;
+ }
+
+ [[nodiscard]] constexpr bool
+ operator==(const stripiter & other) const
+ {
+ return current == other.current;
+ }
+
+ constexpr stripiter &
+ operator++()
+ {
+ ++current;
+ off = 1 - off;
+ return *this;
+ }
+
+ constexpr stripiter &
+ operator--()
+ {
+ --current;
+ off = 1 - off;
+ return *this;
+ }
+
+ constexpr auto
+ operator-(const stripiter & other) const
+ {
+ return current - other.current;
+ }
+
+ constexpr auto
+ operator*() const
+ {
+ return std::tie(*(current - (2 - off)), *(current - off - 1), *current);
+ }
+
+ iter current;
+ uint8_t off {};
+};
+
+template<typename T> struct std::iterator_traits<stripiter<T>> : std::iterator_traits<T> { };
+
+constexpr auto
+strip_begin(IterableCollection auto & cont)
+{
+ return stripiter {cont.begin() + 2};
+}
+
+constexpr auto
+strip_end(IterableCollection auto & cont)
+{
+ return stripiter {cont.end()};
+}
diff --git a/lib/geometricPlane.h b/lib/geometricPlane.h
index 3f95d3c..d4b803d 100644
--- a/lib/geometricPlane.h
+++ b/lib/geometricPlane.h
@@ -16,18 +16,22 @@ public:
template<typename PositionType> class GeometricPlaneT : public GeometricPlane {
public:
+ GeometricPlaneT() = default;
+
+ GeometricPlaneT(PositionType origin, Normal3D normal) : origin(std::move(origin)), normal(normal) { }
+
struct DistAndPosition {
PositionType::value_type dist;
PositionType position;
};
- PositionType origin;
- Normal3D normal;
+ PositionType origin {};
+ Normal3D normal {};
[[nodiscard]] inline PlaneRelation
getRelation(PositionType point) const
{
- const auto d = glm::dot(normal, point - origin);
+ const auto d = glm::dot(normal, RelativePosition3D(point - origin));
return d < 0.F ? PlaneRelation::Below : d > 0.F ? PlaneRelation::Above : PlaneRelation::On;
}
diff --git a/lib/maths.cpp b/lib/maths.cpp
index 68662fc..51e27fe 100644
--- a/lib/maths.cpp
+++ b/lib/maths.cpp
@@ -4,6 +4,11 @@
#include <glm/gtx/rotate_vector.hpp>
#include <glm/gtx/transform.hpp>
+Arc::Arc(const RelativePosition2D & dir0, const RelativePosition2D & dir1) :
+ Arc {vector_yaw(dir0), vector_yaw(dir1)} { }
+
+Arc::Arc(const Angle anga, const Angle angb) : pair {anga, (angb < anga) ? angb + two_pi : angb} { }
+
glm::mat4
flat_orientation(const Direction3D & diff)
{
@@ -76,7 +81,7 @@ rotate_yp(Rotation2D a)
}
float
-vector_yaw(const Direction3D & diff)
+vector_yaw(const Direction2D & diff)
{
return std::atan2(diff.x, diff.y);
}
diff --git a/lib/maths.h b/lib/maths.h
index 5886326..63b752a 100644
--- a/lib/maths.h
+++ b/lib/maths.h
@@ -8,17 +8,28 @@
#include <stdexcept>
#include <utility>
-struct Arc : public std::pair<float, float> {
- using std::pair<float, float>::pair;
+struct Arc : public std::pair<Angle, Angle> {
+ template<glm::length_t Lc, glm::length_t Le, typename T, glm::qualifier Q>
+ requires(Lc >= 2, Le >= 2)
+ Arc(const glm::vec<Lc, T, Q> & centre, const glm::vec<Le, T, Q> & e0p, const glm::vec<Le, T, Q> & e1p) :
+ Arc {RelativePosition2D {e0p.xy() - centre.xy()}, RelativePosition2D {e1p.xy() - centre.xy()}}
+ {
+ }
- template<typename T, glm::qualifier Q>
- Arc(const glm::vec<3, T, Q> & centre3, const glm::vec<3, T, Q> & e0p, const glm::vec<3, T, Q> & e1p);
+ Arc(const RelativePosition2D & dir0, const RelativePosition2D & dir1);
+ Arc(const Angle angb, const Angle anga);
auto
operator[](bool i) const
{
return i ? second : first;
}
+
+ [[nodiscard]] constexpr inline float
+ length() const
+ {
+ return second - first;
+ }
};
constexpr const RelativePosition3D up {0, 0, 1};
@@ -84,9 +95,16 @@ glm::mat4 rotate_pitch(float);
glm::mat4 rotate_yp(Rotation2D);
glm::mat4 rotate_ypr(Rotation3D);
-float vector_yaw(const Direction3D & diff);
+float vector_yaw(const Direction2D & diff);
float vector_pitch(const Direction3D & diff);
+template<typename T, glm::qualifier Q>
+glm::vec<2, T, Q>
+vector_normal(const glm::vec<2, T, Q> & v)
+{
+ return {-v.y, v.x};
+};
+
float round_frac(const float & v, const float & frac);
template<typename T>
@@ -111,7 +129,7 @@ template<std::integral T, glm::qualifier Q>
inline constexpr glm::vec<3, T, Q>
crossProduct(const glm::vec<3, T, Q> a, const glm::vec<3, T, Q> b)
{
- return crossProduct<int64_t, Q>(a, b);
+ return crossProduct<Q>(a, b);
}
template<std::floating_point T, glm::qualifier Q>
@@ -171,12 +189,6 @@ operator%=(glm::vec<L, T, Q> & p, const glm::mat<L + 1, L + 1, T, Q> & mutation)
return p = p % mutation;
}
-constexpr inline float
-arc_length(const Arc & arc)
-{
- return arc.second - arc.first;
-}
-
float normalize(float ang);
template<typename T, glm::qualifier Q>
@@ -244,21 +256,6 @@ midpoint(const std::pair<T, T> & v)
return std::midpoint(v.first, v.second);
}
-template<typename T, glm::qualifier Q>
-Arc::Arc(const glm::vec<3, T, Q> & centre3, const glm::vec<3, T, Q> & e0p, const glm::vec<3, T, Q> & e1p) :
- Arc([&]() -> Arc {
- const auto diffa = e0p - centre3;
- const auto diffb = e1p - centre3;
- const auto anga = vector_yaw(diffa);
- const auto angb = [&diffb, &anga]() {
- const auto angb = vector_yaw(diffb);
- return (angb < anga) ? angb + two_pi : angb;
- }();
- return {anga, angb};
- }())
-{
-}
-
// Conversions
template<typename T>
inline constexpr auto
diff --git a/lib/persistence.h b/lib/persistence.h
index c53ff99..3c95a00 100644
--- a/lib/persistence.h
+++ b/lib/persistence.h
@@ -81,11 +81,11 @@ namespace Persistence {
return make_s<SelectionT<T>>(value);
}
- template<typename S>
+ template<typename S, typename... Extra>
[[nodiscard]] static SelectionPtr
- make_s(T & value)
+ make_s(T & value, Extra &&... extra)
{
- return std::make_unique<S>(value);
+ return std::make_unique<S>(value, std::forward<Extra>(extra)...);
}
T & v;
@@ -331,6 +331,65 @@ namespace Persistence {
}
};
+ template<typename... T> struct SelectionT<std::tuple<T...>> : public SelectionV<std::tuple<T...>> {
+ using V = std::tuple<T...>;
+ using SelectionV<V>::SelectionV;
+
+ struct Members : public SelectionV<V> {
+ template<size_t... Idx>
+ explicit Members(V & v, std::integer_sequence<size_t, Idx...>) :
+ SelectionV<V> {v}, members {SelectionV<std::tuple_element_t<Idx, V>>::make(std::get<Idx>(v))...}
+ {
+ }
+
+ void
+ beforeValue(Stack & stk) override
+ {
+ stk.push(std::move(members[idx++]));
+ }
+
+ std::size_t idx {0};
+ std::array<SelectionPtr, std::tuple_size_v<V>> members;
+ };
+
+ void
+ beginArray(Stack & stk) override
+ {
+ stk.push(this->template make_s<Members>(
+ this->v, std::make_integer_sequence<size_t, std::tuple_size_v<V>>()));
+ }
+ };
+
+ template<typename T, typename U> struct SelectionT<std::pair<T, U>> : public SelectionV<std::pair<T, U>> {
+ using V = std::pair<T, U>;
+ using SelectionV<V>::SelectionV;
+
+ struct Members : public SelectionV<V> {
+ explicit Members(V & v) :
+ SelectionV<V> {v}, members {
+ SelectionV<T>::make(v.first),
+ SelectionV<U>::make(v.second),
+ }
+ {
+ }
+
+ void
+ beforeValue(Stack & stk) override
+ {
+ stk.push(std::move(members[idx++]));
+ }
+
+ std::size_t idx {0};
+ std::array<SelectionPtr, 2> members;
+ };
+
+ void
+ beginArray(Stack & stk) override
+ {
+ stk.push(this->template make_s<Members>(this->v));
+ }
+ };
+
template<typename Map, typename Type = typename Map::mapped_type, auto Key = &Type::element_type::id>
struct MapByMember : public Persistence::SelectionT<Type> {
MapByMember(Map & m) : Persistence::SelectionT<Type> {s}, map {m} { }
diff --git a/lib/ray.h b/lib/ray.h
index e1f43c3..a831270 100644
--- a/lib/ray.h
+++ b/lib/ray.h
@@ -43,15 +43,27 @@ public:
}
bool
+ intersectPlane(const PositionType orig, const Direction3D norm, RelativeDistance & distance) const
+ {
+ if constexpr (std::is_floating_point_v<typename PositionType::value_type>) {
+ return glm::intersectRayPlane(start, direction, orig, norm, distance) && distance >= 0.F;
+ }
+ else {
+ const RelativePosition3D origr = orig - start;
+ return glm::intersectRayPlane({}, direction, origr, norm, distance) && distance >= 0.F;
+ }
+ }
+
+ bool
intersectTriangle(const PositionType t0, const PositionType t1, const PositionType t2, BaryPosition & bary,
RelativeDistance & distance) const
{
if constexpr (std::is_floating_point_v<typename PositionType::value_type>) {
- return glm::intersectRayTriangle(start, direction, t0, t1, t2, bary, distance);
+ return glm::intersectRayTriangle(start, direction, t0, t1, t2, bary, distance) && distance >= 0.F;
}
else {
const RelativePosition3D t0r = t0 - start, t1r = t1 - start, t2r = t2 - start;
- return glm::intersectRayTriangle({}, direction, t0r, t1r, t2r, bary, distance);
+ return glm::intersectRayTriangle({}, direction, t0r, t1r, t2r, bary, distance) && distance >= 0.F;
}
}
diff --git a/lib/stream_support.h b/lib/stream_support.h
index fa536f1..57d82a1 100644
--- a/lib/stream_support.h
+++ b/lib/stream_support.h
@@ -11,17 +11,16 @@
template<typename S>
concept stringlike = requires(const S & s) { s.substr(0); };
template<typename T>
-concept spanable = std::is_constructible_v<std::span<const typename T::value_type>, T> && !stringlike<T>
- && !std::is_same_v<std::span<typename T::value_type>, T>;
+concept NonStringIterableCollection
+ = std::is_same_v<decltype(std::declval<T>().begin()), decltype(std::declval<T>().end())> && !stringlike<T>;
namespace std {
- template<typename T, std::size_t L>
std::ostream &
- operator<<(std::ostream & s, const span<T, L> v)
+ operator<<(std::ostream & s, const NonStringIterableCollection auto & v)
{
s << '(';
for (const auto & i : v) {
- if (&i != &v.front()) {
+ if (&i != &*v.begin()) {
s << ", ";
}
s << i;
@@ -43,13 +42,6 @@ namespace std {
return (s << std::span {&v[0], L});
}
- template<spanable T>
- std::ostream &
- operator<<(std::ostream & s, const T & v)
- {
- return (s << std::span {v});
- }
-
template<typename First, typename Second>
std::ostream &
operator<<(std::ostream & s, const std::pair<First, Second> & v)