HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
bezier_point.hpp
1// Copyright Take Vos 2019, 2021.
2// Distributed under the Boost Software License, Version 1.0.
3// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
4
5#pragma once
6
7#include "geometry/module.hpp"
8#include "utility/module.hpp"
9#include <vector>
10
11namespace hi::inline v1 {
12
17 enum class Type { Anchor, QuadraticControl, CubicControl1, CubicControl2 };
18
19 Type type;
20 point2 p;
21
22 bezier_point(point2 const p, Type const type) noexcept : type(type), p(p) {}
23
24 bezier_point(float const x, float const y, Type const type) noexcept : bezier_point(point2{x, y}, type) {}
25
39 std::vector<bezier_point>::const_iterator const begin,
40 std::vector<bezier_point>::const_iterator const end) noexcept
41 {
43
44 hi_axiom((end - begin) >= 2);
45
46 auto prev_it = end - 1;
47 auto prev_prev_it = end - 2;
48 for (auto it = begin; it != end; it++) {
49 switch (it->type) {
50 case bezier_point::Type::Anchor:
51 hi_axiom(prev_it->type != bezier_point::Type::CubicControl1);
52 r.push_back(*it);
53 break;
54
55 case bezier_point::Type::QuadraticControl:
56 if (it->type == bezier_point::Type::QuadraticControl) {
57 r.emplace_back(midpoint(prev_it->p, it->p), bezier_point::Type::Anchor);
58
59 } else {
60 hi_axiom(prev_it->type == bezier_point::Type::Anchor);
61 }
62 r.push_back(*it);
63 break;
64
65 case bezier_point::Type::CubicControl1: r.push_back(*it); break;
66
67 case bezier_point::Type::CubicControl2:
68 if (prev_it->type == bezier_point::Type::Anchor) {
69 hi_axiom(prev_prev_it->type == bezier_point::Type::CubicControl2);
70
71 r.emplace_back(reflect(prev_prev_it->p, prev_it->p), bezier_point::Type::CubicControl1);
72 } else {
73 hi_axiom(prev_it->type == bezier_point::Type::CubicControl1);
74 }
75 r.push_back(*it);
76 break;
77
78 default: hi_no_default();
79 }
80
81 prev_prev_it = prev_it;
82 prev_it = it;
83 }
84
85 for (ssize_t i = 0; i < ssize(r); i++) {
86 if (r[i].type == bezier_point::Type::Anchor) {
87 std::rotate(r.begin(), r.begin() + i, r.end());
88 r.push_back(r.front());
89 return r;
90 }
91 }
92
93 // The result did not contain an anchor.
95 }
96
97 [[nodiscard]] friend bool operator==(bezier_point const &lhs, bezier_point const &rhs) noexcept
98 {
99 return (lhs.p == rhs.p) && (lhs.type == rhs.type);
100 }
101
104 [[nodiscard]] friend bezier_point operator*(geo::transformer auto const &lhs, bezier_point const &rhs) noexcept
105 {
106 return {lhs * rhs.p, rhs.type};
107 }
108};
109
110} // namespace hi::inline v1
#define hi_no_default(...)
This part of the code should not be reachable, unless a programming bug.
Definition assert.hpp:264
#define hi_axiom(expression,...)
Specify an axiom; an expression that is true.
Definition assert.hpp:238
DOXYGEN BUG.
Definition algorithm.hpp:13
Definition bezier_point.hpp:16
static std::vector< bezier_point > normalizePoints(std::vector< bezier_point >::const_iterator const begin, std::vector< bezier_point >::const_iterator const end) noexcept
Definition bezier_point.hpp:38
friend bezier_point operator*(geo::transformer auto const &lhs, bezier_point const &rhs) noexcept
Transform the point.
Definition bezier_point.hpp:104
Definition transform.hpp:84
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)