#ifndef BWIDGETS_MATH_HPP #define BWIDGETS_MATH_HPP #include #include #include #include #include namespace bwidgets { // Get the start coordinate offset required to center a ligne with a length used_len on another // line with a length available_len. [[nodiscard]] inline auto center_line(const int available_len, const int used_len) noexcept -> int { return (available_len - used_len) / 2; } // Get the squared distance of two points on a 2D plan. This avoid computing square root // when for instance we need to compare two lenght but knowing the actual lenght is not // needed. [[nodiscard]] inline auto distance_sqrd(const SDL_Point a, const SDL_Point b) noexcept -> float { return float(a.x - b.x) * float(a.x - b.x) + float(a.y - b.y) * float(a.y - b.y); } // Get distance of two points on a 2D plan. [[nodiscard]] inline auto distance(const SDL_Point a, const SDL_Point b) noexcept -> float { return std::sqrt(distance_sqrd(a, b)); } // Like std::lerp but for use with Color object. lerp function is applied only to enabled channels. template [[nodiscard]] inline auto lerp(const Color a, const Color b, const F x, const bool op_alpha=false, const bool op_color=true) noexcept -> Color { return {{ op_color ? (uint8_t)std::lerp(a().r, b().r, x) : a().r, op_color ? (uint8_t)std::lerp(a().g, b().g, x) : a().g, op_color ? (uint8_t)std::lerp(a().b, b().b, x) : a().b, op_alpha ? (uint8_t)std::lerp(a().a, b().a, x) : a().a, }}; } // Reverse lerp. template [[nodiscard]] inline auto linear(const N x, const N a, const N b) noexcept -> float { return (float)(x - a) / (float)(b - a); } // Check if a rectangle is completly inside of another rectangle. [[nodiscard]] inline auto rect_in_rect(const SDL_Rect& outer, const SDL_Rect& inner) noexcept -> bool { const SDL_Point top_left {inner.x, inner.y}; const SDL_Point bottom_right {inner.x + inner.w, inner.y + inner.h}; return (SDL_PointInRect(&top_left, &outer) == SDL_TRUE) && (SDL_PointInRect(&bottom_right, &outer) == SDL_TRUE); } // Get the rectangle inside r leaving margins of given size between inner and outer rectangle. [[nodiscard]] inline auto rect_margin(const SDL_Rect& r, const Size margin) noexcept -> SDL_Rect { return {r.x + margin.w, r.y + margin.h, r.w - 2 * margin.w, r.h - 2 * margin.h}; } // Get the rectangle obtained from adding offset to its origin coordinate. [[nodiscard]] inline auto rect_offset(const SDL_Rect& r, const SDL_Point offset) noexcept -> SDL_Rect { return {r.x + offset.x, r.y + offset.y, r.w, r.h}; } // Commodity function to use another rectangle as a size for the offset to be added to r. [[nodiscard]] inline auto rect_offset(const SDL_Rect& r, const SDL_Rect& offset) noexcept -> SDL_Rect { return rect_offset(r, SDL_Point {offset.x, offset.y}); } // Standard smoothstep algorithm. template [[nodiscard]] inline auto smoothstep(const N x, const N a, const N b) noexcept -> float { const float x_norm = linear(std::clamp(x, a, b), a, b); return 3 * x_norm * x_norm - 2 * x_norm * x_norm * x_norm; } } #endif