HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
scale.hpp
1// Copyright Take Vos 2021-2022.
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 "matrix.hpp"
8#include "identity.hpp"
9#include "translate.hpp"
10#include "extent.hpp"
11
12namespace hi::inline v1 {
13namespace geo {
14
15template<int D>
16class scale {
17public:
18 static_assert(D == 2 || D == 3, "Only 2D or 3D scale-matrices are supported");
19
20 constexpr scale(scale const &) noexcept = default;
21 constexpr scale(scale &&) noexcept = default;
22 constexpr scale &operator=(scale const &) noexcept = default;
23 constexpr scale &operator=(scale &&) noexcept = default;
24
25 [[nodiscard]] constexpr explicit operator f32x4() const noexcept
26 {
27 hi_axiom(holds_invariant());
28 return _v;
29 }
30
31 [[nodiscard]] constexpr explicit operator extent<2>() const noexcept requires(D == 2)
32 {
33 return extent<2>{_v.xy00()};
34 }
35
36 [[nodiscard]] constexpr explicit operator extent<3>() const noexcept requires(D == 3)
37 {
38 return extent<3>{_v.xyz0()};
39 }
40
41 [[nodiscard]] constexpr explicit scale(f32x4 const &v) noexcept : _v(v)
42 {
43 hi_axiom(holds_invariant());
44 }
45
46 template<int E>
47 requires(E <= D) [[nodiscard]] constexpr explicit scale(vector<E> const &v) noexcept : _v(static_cast<f32x4>(v).xyz1())
48 {
49 hi_axiom(holds_invariant());
50 }
51
52 [[nodiscard]] constexpr operator matrix<D>() const noexcept
53 {
54 hi_axiom(holds_invariant());
55 return matrix<D>{_v.x000(), _v._0y00(), _v._00z0(), _v._000w()};
56 }
57
58 [[nodiscard]] constexpr scale() noexcept : _v(1.0, 1.0, 1.0, 1.0) {}
59
60 [[nodiscard]] constexpr scale(identity const &) noexcept : _v(1.0, 1.0, 1.0, 1.0) {}
61
62 [[nodiscard]] constexpr scale(float value) noexcept requires(D == 2) : _v(value, value, 1.0, 1.0) {}
63
64 [[nodiscard]] constexpr scale(float value) noexcept requires(D == 3) : _v(value, value, value, 1.0) {}
65
66 [[nodiscard]] constexpr scale(float x, float y) noexcept requires(D == 2) : _v(x, y, 1.0, 1.0) {}
67
68 [[nodiscard]] constexpr scale(float x, float y, float z = 1.0) noexcept requires(D == 3) : _v(x, y, z, 1.0) {}
69
75 template<int E, int F>
76 requires(E <= D && F <= D) [[nodiscard]] static constexpr scale uniform(extent<E> src_extent, extent<F> dst_extent) noexcept
77 {
79 dst_extent.width() != 0.0f && src_extent.width() != 0.0f && dst_extent.height() != 0.0f &&
80 src_extent.height() != 0.0f);
81
82 if constexpr (D == 2) {
83 hilet non_uniform_scale = static_cast<f32x4>(dst_extent).xyxy() / static_cast<f32x4>(src_extent).xyxy();
84 hilet uniform_scale = std::min(non_uniform_scale.x(), non_uniform_scale.y());
85 return scale{uniform_scale};
86
87 } else if constexpr (D == 3) {
88 hi_axiom(dst_extent.z() != 0.0f && src_extent.z() != 0.0f);
89 hilet non_uniform_scale = static_cast<f32x4>(dst_extent).xyzx() / static_cast<f32x4>(src_extent).xyzx();
90 hilet uniform_scale = std::min({non_uniform_scale.x(), non_uniform_scale.y(), non_uniform_scale.z()});
91 return scale{uniform_scale};
92
93 } else {
95 }
96 }
97
98 template<int E>
99 [[nodiscard]] constexpr vector<E> operator*(vector<E> const &rhs) const noexcept
100 {
101 hi_axiom(holds_invariant() && rhs.holds_invariant());
102 return vector<E>{_v * static_cast<f32x4>(rhs)};
103 }
104
105 template<int E>
106 [[nodiscard]] constexpr extent<E> operator*(extent<E> const &rhs) const noexcept
107 {
108 hi_axiom(holds_invariant() && rhs.holds_invariant());
109 return extent<E>{_v * static_cast<f32x4>(rhs)};
110 }
111
112 template<int E>
113 [[nodiscard]] constexpr point<E> operator*(point<E> const &rhs) const noexcept
114 {
115 hi_axiom(holds_invariant() && rhs.holds_invariant());
116 return point<E>{_v * static_cast<f32x4>(rhs)};
117 }
118
121 [[nodiscard]] constexpr aarectangle operator*(aarectangle const &rhs) const noexcept requires(D == 2)
122 {
123 return aarectangle{*this * get<0>(rhs), *this * get<3>(rhs)};
124 }
125
126 [[nodiscard]] constexpr rectangle operator*(rectangle const &rhs) const noexcept
127 {
128 return rectangle{*this * get<0>(rhs), *this * get<1>(rhs), *this * get<2>(rhs), *this * get<3>(rhs)};
129 }
130
131 [[nodiscard]] constexpr quad operator*(quad const &rhs) const noexcept
132 {
133 return quad{*this * rhs.p0, *this * rhs.p1, *this * rhs.p2, *this * rhs.p3};
134 }
135
144 [[nodiscard]] friend constexpr quad scale_from_center(quad const &lhs, scale const &rhs) noexcept requires(D == 2)
145 {
146 hilet top_extra = (lhs.top() * rhs._v.x() - lhs.top()) * 0.5f;
147 hilet bottom_extra = (lhs.bottom() * rhs._v.x() - lhs.bottom()) * 0.5f;
148 hilet left_extra = (lhs.left() * rhs._v.y() - lhs.left()) * 0.5f;
149 hilet right_extra = (lhs.right() * rhs._v.y() - lhs.right()) * 0.5f;
150
151 return {
152 lhs.p0 - bottom_extra - left_extra,
153 lhs.p1 + bottom_extra - right_extra,
154 lhs.p2 - top_extra + left_extra,
155 lhs.p3 + top_extra + right_extra};
156 }
157
158 [[nodiscard]] constexpr scale operator*(identity const &) const noexcept
159 {
160 hi_axiom(holds_invariant());
161 return *this;
162 }
163
164 template<int E>
165 [[nodiscard]] constexpr auto operator*(scale<E> const &rhs) const noexcept
166 {
167 hi_axiom(holds_invariant() && rhs.holds_invariant());
168 return scale<std::max(D, E)>{_v * static_cast<f32x4>(rhs)};
169 }
170
171 template<int E>
172 [[nodiscard]] constexpr bool operator==(scale<E> const &rhs) const noexcept
173 {
174 hi_axiom(holds_invariant() && rhs.holds_invariant());
175 return _v == static_cast<f32x4>(rhs);
176 }
177
178 [[nodiscard]] constexpr bool holds_invariant() const noexcept
179 {
180 if constexpr (D == 3) {
181 return _v.w() == 1.0f;
182 } else {
183 return _v.z() == 1.0f and _v.w() == 1.0f;
184 }
185 }
186
187private:
188 f32x4 _v;
189};
190
191[[nodiscard]] constexpr scale<2> operator/(extent<2> const &lhs, extent<2> const &rhs) noexcept
192{
193 hi_axiom(rhs._v.x() != 0.0f);
194 hi_axiom(rhs._v.y() != 0.0f);
195 return scale<2>{lhs._v.xy11() / rhs._v.xy11()};
196}
197
198[[nodiscard]] constexpr scale<3> operator/(extent<3> const &lhs, extent<3> const &rhs) noexcept
199{
200 hi_axiom(rhs._v.x() != 0.0f);
201 hi_axiom(rhs._v.y() != 0.0f);
202 hi_axiom(rhs._v.z() != 0.0f);
203 return scale<3>{lhs._v.xyz1() / rhs._v.xyz1()};
204}
205
206template<int D>
207[[nodiscard]] constexpr matrix<D>
208matrix<D>::uniform(aarectangle src_rectangle, aarectangle dst_rectangle, alignment alignment) noexcept
209{
210 hilet scale = hi::geo::scale<D>::uniform(src_rectangle.size(), dst_rectangle.size());
211 hilet scaled_rectangle = scale * src_rectangle;
212 hilet translation = translate<D>::align(scaled_rectangle, dst_rectangle, alignment);
213 return translation * scale;
214}
215
216} // namespace geo
217
218using scale2 = geo::scale<2>;
219using scale3 = geo::scale<3>;
220
221} // namespace hi::inline v1
#define hi_axiom(expression)
Specify an axiom; an expression that is true.
Definition assert.hpp:133
#define hi_static_no_default()
This part of the code should not be reachable, unless a programming bug.
Definition assert.hpp:172
#define hilet
Invariant should be the default for variables.
Definition utility.hpp:23
DOXYGEN BUG.
Definition algorithm.hpp:15
Definition alignment.hpp:75
Class which represents an axis-aligned rectangle.
Definition axis_aligned_rectangle.hpp:20
Definition scale.hpp:16
constexpr aarectangle operator*(aarectangle const &rhs) const noexcept
Scale a rectangle around it's center.
Definition scale.hpp:121
friend constexpr quad scale_from_center(quad const &lhs, scale const &rhs) noexcept
scale the quad.
Definition scale.hpp:144
static constexpr scale uniform(extent< E > src_extent, extent< F > dst_extent) noexcept
Get a uniform-scale-transform to scale an extent to another extent.
Definition scale.hpp:76
A high-level geometric extent.
Definition extent.hpp:23
constexpr float & height() noexcept
Access the y-as-height element from the extent.
Definition extent.hpp:151
constexpr float & width() noexcept
Access the x-as-width element from the extent.
Definition extent.hpp:140
Definition matrix.hpp:23
Definition quad.hpp:17
point3 p0
Left-bottom.
Definition quad.hpp:19
A rectangle / parallelogram in 3D space.
Definition rectangle.hpp:20
Definition translate.hpp:15
A high-level geometric vector Part of the high-level vector, point, mat and color types.
Definition vector.hpp:21
T max(T... args)
T min(T... args)