17 static_assert(D == 2 || D == 3,
"Only 2D or 3D translation-matrices are supported");
20 using array_type = simd<value_type, 4>;
27 [[nodiscard]]
constexpr operator matrix<2>()
const noexcept
28 requires std::is_same_v<value_type, float> and (D == 2)
31 hilet ones = array_type::broadcast(value_type{1});
32 return matrix<2>{ones.x000(), ones._0y00(), ones._00z0(), ones._000w() + _v};
35 [[nodiscard]]
constexpr operator matrix<3>()
const noexcept
36 requires std::is_same_v<value_type, float>
39 hilet ones = array_type::broadcast(value_type{1});
40 return matrix<3>{ones.x000(), ones._0y00(), ones._00z0(), ones._000w() + _v};
43 [[nodiscard]]
constexpr translate() noexcept : _v() {}
47 [[nodiscard]]
constexpr explicit operator array_type()
const noexcept
53 [[nodiscard]]
constexpr explicit translate(array_type
const& other) noexcept : _v(other)
58 [[nodiscard]]
constexpr explicit translate(axis_aligned_rectangle<value_type>
const& other) noexcept :
59 _v(
static_cast<array_type
>(get<0>(other)).xy00())
64 [[nodiscard]]
constexpr explicit translate(axis_aligned_rectangle<value_type>
const& other, value_type z)
noexcept
66 : _v(
static_cast<array_type
>(get<0>(other)).xy00())
82 _v(
static_cast<array_type
>(other))
98 _v(
static_cast<array_type
>(other).xyz0())
103 [[nodiscard]]
constexpr translate(value_type x, value_type y)
noexcept
105 : _v(x, y, value_type{0}, value_type{0})
109 [[nodiscard]]
constexpr translate(value_type x, value_type y, value_type z = value_type{0})
noexcept
111 : _v(x, y, z, value_type{0})
115 [[nodiscard]]
constexpr value_type x()
const noexcept
120 [[nodiscard]]
constexpr value_type y()
const noexcept
126 [[nodiscard]]
constexpr value_type z()
const noexcept
132 [[nodiscard]]
constexpr value_type& x()
noexcept
137 [[nodiscard]]
constexpr value_type& y()
noexcept
143 [[nodiscard]]
constexpr value_type& z()
noexcept
156 axis_aligned_rectangle<value_type> src_rectangle,
157 axis_aligned_rectangle<value_type> dst_rectangle,
160 auto x = value_type{0};
161 if (
alignment == horizontal_alignment::left) {
162 x = dst_rectangle.left();
164 }
else if (
alignment == horizontal_alignment::right) {
165 x = dst_rectangle.right() - src_rectangle.width();
167 }
else if (
alignment == horizontal_alignment::center) {
168 x = dst_rectangle.center() - src_rectangle.width() * 0.5f;
174 auto y = value_type{0};
175 if (
alignment == vertical_alignment::bottom) {
176 y = dst_rectangle.bottom();
178 }
else if (
alignment == vertical_alignment::top) {
179 y = dst_rectangle.top() - src_rectangle.height();
181 }
else if (
alignment == vertical_alignment::middle) {
182 y = dst_rectangle.middle() - src_rectangle.height() * 0.5f;
188 return translate{x - src_rectangle.left(), y - src_rectangle.bottom()};
195 hi_axiom(holds_invariant() && rhs.holds_invariant());
200 [[nodiscard]]
constexpr point<value_type,
std::max(D, E)> operator*(point<value_type, E>
const& rhs)
const noexcept
202 hi_axiom(holds_invariant() && rhs.holds_invariant());
203 return point<value_type,
std::max(D, E)>{_v +
static_cast<array_type
>(rhs)};
206 constexpr friend point<value_type, 2>& operator*=(point<value_type, 2>& lhs, translate
const& rhs)
noexcept
209 return lhs = rhs * lhs;
212 [[nodiscard]]
constexpr axis_aligned_rectangle<value_type>
213 operator*(axis_aligned_rectangle<value_type>
const& rhs)
const noexcept
216 return axis_aligned_rectangle<value_type>{*
this * get<0>(rhs), *
this * get<3>(rhs)};
219 constexpr friend axis_aligned_rectangle<value_type>&
220 operator*=(axis_aligned_rectangle<value_type>& lhs, translate
const& rhs)
noexcept
223 return lhs = rhs * lhs;
226 [[nodiscard]]
constexpr rectangle operator*(axis_aligned_rectangle<value_type>
const& rhs)
const noexcept
227 requires std::is_same_v<value_type, float> and (D == 3)
232 [[nodiscard]]
constexpr rectangle operator*(rectangle
const& rhs)
const noexcept
233 requires std::is_same_v<value_type, float>
235 return rectangle{*
this * rhs.origin, rhs.right, rhs.up};
238 [[nodiscard]]
constexpr quad operator*(quad
const& rhs)
const noexcept
239 requires std::is_same_v<value_type, float>
241 return quad{*
this * rhs.p0, *
this * rhs.p1, *
this * rhs.p2, *
this * rhs.p3};
244 [[nodiscard]]
constexpr circle operator*(circle
const& rhs)
const noexcept
245 requires std::is_same_v<value_type, float>
247 return circle{array_type{rhs} + _v};
250 [[nodiscard]]
constexpr line_segment operator*(line_segment
const& rhs)
const noexcept
251 requires std::is_same_v<value_type, float>
253 return line_segment{*
this * rhs.origin(), rhs.direction()};
256 [[nodiscard]]
constexpr translate operator*(identity
const&)
const noexcept
263 [[nodiscard]]
constexpr auto operator*(matrix<E>
const& rhs)
const noexcept
264 requires std::is_same_v<value_type, float>
266 hi_axiom(holds_invariant() && rhs.holds_invariant());
267 return matrix<
std::max(D, E)>{get<0>(rhs), get<1>(rhs), get<2>(rhs), get<3>(rhs) + _v};
271 [[nodiscard]]
constexpr auto operator*(rotate<E>
const& rhs)
const noexcept
272 requires std::is_same_v<value_type, float>
274 return *
this * matrix<E>(rhs);
278 [[nodiscard]]
constexpr auto operator*(translate<value_type, E>
const& rhs)
const noexcept
280 hi_axiom(holds_invariant() && rhs.holds_invariant());
281 return translate<value_type,
std::max(D, E)>{_v +
static_cast<array_type
>(rhs)};
285 [[nodiscard]]
constexpr bool operator==(translate<value_type, E>
const& rhs)
const noexcept
287 hi_axiom(holds_invariant() && rhs.holds_invariant());
288 return equal(_v,
static_cast<array_type
>(rhs));
291 [[nodiscard]]
constexpr translate operator~() const noexcept
293 return translate{-_v};
296 [[nodiscard]]
constexpr bool holds_invariant() const noexcept
298 return _v.w() == value_type{0} && (D == 3 || _v.z() == value_type{0});
301 [[nodiscard]]
friend constexpr translate
round(translate
const& rhs)
noexcept
302 requires std::is_same_v<value_type, float>
304 return translate{
round(rhs._v)};