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 "required.hpp"
8#include "cast.hpp"
9#include "geometry/point.hpp"
10#include "geometry/transform.hpp"
11#include <vector>
12
13namespace tt {
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 }
27
28 bezier_point(float const x, float const y, Type const type) noexcept : bezier_point(point2{x, y}, type) {}
29
43 std::vector<bezier_point>::const_iterator const begin,
44 std::vector<bezier_point>::const_iterator const end) noexcept
45 {
47
48 tt_assert((end - begin) >= 2);
49
50 auto previousPoint = *(end - 1);
51 auto previousPreviousPoint = *(end - 2);
52 for (auto i = begin; i != end; i++) {
53 ttlet point = *i;
54
55 switch (point.type) {
56 case bezier_point::Type::Anchor:
57 tt_assert(previousPoint.type != bezier_point::Type::CubicControl1);
58 r.push_back(point);
59 break;
60
61 case bezier_point::Type::QuadraticControl:
62 if (previousPoint.type == bezier_point::Type::QuadraticControl) {
63 r.emplace_back(midpoint(previousPoint.p, point.p), bezier_point::Type::Anchor);
64
65 } else {
66 tt_assert(previousPoint.type == bezier_point::Type::Anchor);
67 }
68 r.push_back(point);
69 break;
70
71 case bezier_point::Type::CubicControl1: r.push_back(point); break;
72
73 case bezier_point::Type::CubicControl2:
74 if (previousPoint.type == bezier_point::Type::Anchor) {
75 tt_assert(previousPreviousPoint.type == bezier_point::Type::CubicControl2);
76
77 r.emplace_back(reflect(previousPreviousPoint.p, previousPoint.p), bezier_point::Type::CubicControl1);
78 } else {
79 tt_assert(previousPoint.type == bezier_point::Type::CubicControl1);
80 }
81 r.push_back(point);
82 break;
83
84 default: tt_no_default();
85 }
86
87 previousPreviousPoint = previousPoint;
88 previousPoint = point;
89 }
90
91 for (ssize_t i = 0; i < std::ssize(r); i++) {
92 if (r[i].type == bezier_point::Type::Anchor) {
93 std::rotate(r.begin(), r.begin() + i, r.end());
94 r.push_back(r.front());
95 return r;
96 }
97 }
98
99 // The result did not contain an anchor.
100 tt_assert(false);
101 }
102
103 [[nodiscard]] friend bool operator==(bezier_point const &lhs, bezier_point const &rhs) noexcept
104 {
105 return (lhs.p == rhs.p) && (lhs.type == rhs.type);
106 }
107
110 [[nodiscard]] friend bezier_point operator*(geo::transformer auto const &lhs, bezier_point const &rhs) noexcept {
111 return {lhs * rhs.p, rhs.type};
112 }
113};
114
115} // namespace tt
Definition bezier_point.hpp:18
friend bezier_point operator*(geo::transformer auto const &lhs, bezier_point const &rhs) noexcept
Transform the point.
Definition bezier_point.hpp:110
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:42
Definition transform.hpp:83
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)