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 "utility.hpp"
8#include "cast.hpp"
9#include "geometry/point.hpp"
10#include "geometry/transform.hpp"
11#include <vector>
12
13namespace hi::inline v1 {
14
19 enum class Type { Anchor, QuadraticControl, CubicControl1, CubicControl2 };
20
21 Type type;
22 point2 p;
23
24 bezier_point(point2 const p, Type const type) noexcept : type(type), p(p) {}
25
26 bezier_point(float const x, float const y, Type const type) noexcept : bezier_point(point2{x, y}, type) {}
27
41 std::vector<bezier_point>::const_iterator const begin,
42 std::vector<bezier_point>::const_iterator const end) noexcept
43 {
45
46 hi_axiom((end - begin) >= 2);
47
48 auto prev_it = end - 1;
49 auto prev_prev_it = end - 2;
50 for (auto it = begin; it != end; it++) {
51 switch (it->type) {
52 case bezier_point::Type::Anchor:
53 hi_axiom(prev_it->type != bezier_point::Type::CubicControl1);
54 r.push_back(*it);
55 break;
56
57 case bezier_point::Type::QuadraticControl:
58 if (it->type == bezier_point::Type::QuadraticControl) {
59 r.emplace_back(midpoint(prev_it->p, it->p), bezier_point::Type::Anchor);
60
61 } else {
62 hi_axiom(prev_it->type == bezier_point::Type::Anchor);
63 }
64 r.push_back(*it);
65 break;
66
67 case bezier_point::Type::CubicControl1: r.push_back(*it); break;
68
69 case bezier_point::Type::CubicControl2:
70 if (prev_it->type == bezier_point::Type::Anchor) {
71 hi_axiom(prev_prev_it->type == bezier_point::Type::CubicControl2);
72
73 r.emplace_back(reflect(prev_prev_it->p, prev_it->p), bezier_point::Type::CubicControl1);
74 } else {
75 hi_axiom(prev_it->type == bezier_point::Type::CubicControl1);
76 }
77 r.push_back(*it);
78 break;
79
80 default: hi_no_default();
81 }
82
83 prev_prev_it = prev_it;
84 prev_it = it;
85 }
86
87 for (ssize_t i = 0; i < ssize(r); i++) {
88 if (r[i].type == bezier_point::Type::Anchor) {
89 std::rotate(r.begin(), r.begin() + i, r.end());
90 r.push_back(r.front());
91 return r;
92 }
93 }
94
95 // The result did not contain an anchor.
97 }
98
99 [[nodiscard]] friend bool operator==(bezier_point const &lhs, bezier_point const &rhs) noexcept
100 {
101 return (lhs.p == rhs.p) && (lhs.type == rhs.type);
102 }
103
106 [[nodiscard]] friend bezier_point operator*(geo::transformer auto const &lhs, bezier_point const &rhs) noexcept
107 {
108 return {lhs * rhs.p, rhs.type};
109 }
110};
111
112} // namespace hi::inline v1
#define hi_no_default(...)
This part of the code should not be reachable, unless a programming bug.
Definition assert.hpp:148
#define hi_axiom(expression,...)
Specify an axiom; an expression that is true.
Definition assert.hpp:133
Utilities used by the HikoGUI library itself.
DOXYGEN BUG.
Definition algorithm.hpp:15
Definition bezier_point.hpp:18
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:40
friend bezier_point operator*(geo::transformer auto const &lhs, bezier_point const &rhs) noexcept
Transform the point.
Definition bezier_point.hpp:106
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)