HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
BezierPoint.hpp
1// Copyright 2019 Pokitec
2// All rights reserved.
3
4#pragma once
5
6#include "TTauri/Foundation/required.hpp"
7#include "TTauri/Foundation/numeric_cast.hpp"
8#include "TTauri/Foundation/vec.hpp"
9#include "TTauri/Foundation/mat.hpp"
10#include <vector>
11
12namespace tt {
13
18 enum class Type { Anchor, QuadraticControl, CubicControl1, CubicControl2 };
19
20 Type type;
21 vec p;
22
23 BezierPoint(vec const p, Type const type) noexcept : type(type), p(p) {
24 tt_assume(p.is_point());
25 }
26
27 BezierPoint(float const x, float const y, Type const type) noexcept : BezierPoint(vec::point(x, y), type) {}
28
42 std::vector<BezierPoint>::const_iterator const begin,
43 std::vector<BezierPoint>::const_iterator const end
44 ) noexcept {
46
47 tt_assert((end - begin) >= 2);
48
49 auto previousPoint = *(end - 1);
50 auto previousPreviousPoint = *(end - 2);
51 for (auto i = begin; i != end; i++) {
52 ttlet point = *i;
53
54 switch (point.type) {
55 case BezierPoint::Type::Anchor:
56 tt_assert(previousPoint.type != BezierPoint::Type::CubicControl1);
57 r.push_back(point);
58 break;
59
60 case BezierPoint::Type::QuadraticControl:
61 if (previousPoint.type == BezierPoint::Type::QuadraticControl) {
62 r.emplace_back(midpoint(previousPoint.p, point.p), BezierPoint::Type::Anchor);
63
64 } else {
65 tt_assert(previousPoint.type == BezierPoint::Type::Anchor);
66 }
67 r.push_back(point);
68 break;
69
70 case BezierPoint::Type::CubicControl1:
71 r.push_back(point);
72 break;
73
74 case BezierPoint::Type::CubicControl2:
75 if (previousPoint.type == BezierPoint::Type::Anchor) {
76 tt_assert(previousPreviousPoint.type == BezierPoint::Type::CubicControl2);
77
78 r.emplace_back(reflect_point(previousPreviousPoint.p, previousPoint.p), BezierPoint::Type::CubicControl1);
79 } else {
80 tt_assert(previousPoint.type == BezierPoint::Type::CubicControl1);
81 }
82 r.push_back(point);
83 break;
84
85 default:
86 tt_no_default;
87 }
88
89 previousPreviousPoint = previousPoint;
90 previousPoint = point;
91 }
92
93 for (ssize_t i = 0; i < ssize(r); i++) {
94 if (r[i].type == BezierPoint::Type::Anchor) {
95 std::rotate(r.begin(), r.begin() + i, r.end());
96 r.push_back(r.front());
97 return r;
98 }
99 }
100
101 // The result did not contain an anchor.
102 tt_assert(false);
103 }
104
107 template<typename M, std::enable_if_t<is_mat_v<M>, int> = 0>
108 inline BezierPoint &operator*=(M const &rhs) noexcept {
109 p = rhs * p;
110 return *this;
111 }
112
113 [[nodiscard]] friend bool operator==(BezierPoint const &lhs, BezierPoint const &rhs) noexcept {
114 return (lhs.p == rhs.p) && (lhs.type == rhs.type);
115 }
116
119 template<typename M, std::enable_if_t<is_mat_v<M>, int> = 0>
120 [[nodiscard]] friend BezierPoint operator*(M const &lhs, BezierPoint const &rhs) noexcept {
121 return { lhs * rhs.p, rhs.type };
122 }
123};
124
125}
Definition BezierPoint.hpp:17
friend BezierPoint operator*(M const &lhs, BezierPoint const &rhs) noexcept
Transform the point.
Definition BezierPoint.hpp:120
BezierPoint & operator*=(M const &rhs) noexcept
Transform the point.
Definition BezierPoint.hpp:108
static std::vector< BezierPoint > normalizePoints(std::vector< BezierPoint >::const_iterator const begin, std::vector< BezierPoint >::const_iterator const end) noexcept
Definition BezierPoint.hpp:41
A 4D vector.
Definition vec.hpp:37
static tt_force_inline vec point(float x=0.0f, float y=0.0f, float z=0.0f) noexcept
Create a point out of 2 to 4 values.
Definition vec.hpp:180
T begin(T... args)
T emplace_back(T... args)
T end(T... args)
T front(T... args)
T push_back(T... args)
T rotate(T... args)