-module(viva_math@vec2). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/viva_math/vec2.gleam"). -export([zero/0, splat/1, from_polar/2, add/2, sub/2, scale/2, negate/1, dot/2, cross/2, length_squared/1, length/1, distance/2, normalize/1, lerp/3, clamp/3, rotate/2, perpendicular/1, angle/1, is_close/3]). -export_type([vec2/0]). -if(?OTP_RELEASE >= 27). -define(MODULEDOC(Str), -moduledoc(Str)). -define(DOC(Str), -doc(Str)). -else. -define(MODULEDOC(Str), -compile([])). -define(DOC(Str), -compile([])). -endif. ?MODULEDOC( " 2-D vector operations.\n" "\n" " Companion to `viva_math/vector` (which is dedicated to PAD/Vec3).\n" " Useful for 2-D dynamics, planar geometry, polar coordinates, etc.\n" ). -type vec2() :: {vec2, float(), float()}. -file("src/viva_math/vec2.gleam", 13). -spec zero() -> vec2(). zero() -> {vec2, +0.0, +0.0}. -file("src/viva_math/vec2.gleam", 17). -spec splat(float()) -> vec2(). splat(Value) -> {vec2, Value, Value}. -file("src/viva_math/vec2.gleam", 21). -spec from_polar(float(), float()) -> vec2(). from_polar(R, Theta) -> {vec2, R * math:cos(Theta), R * math:sin(Theta)}. -file("src/viva_math/vec2.gleam", 25). -spec add(vec2(), vec2()) -> vec2(). add(A, B) -> {vec2, erlang:element(2, A) + erlang:element(2, B), erlang:element(3, A) + erlang:element(3, B)}. -file("src/viva_math/vec2.gleam", 29). -spec sub(vec2(), vec2()) -> vec2(). sub(A, B) -> {vec2, erlang:element(2, A) - erlang:element(2, B), erlang:element(3, A) - erlang:element(3, B)}. -file("src/viva_math/vec2.gleam", 33). -spec scale(vec2(), float()) -> vec2(). scale(V, S) -> {vec2, erlang:element(2, V) * S, erlang:element(3, V) * S}. -file("src/viva_math/vec2.gleam", 37). -spec negate(vec2()) -> vec2(). negate(V) -> {vec2, +0.0 - erlang:element(2, V), +0.0 - erlang:element(3, V)}. -file("src/viva_math/vec2.gleam", 41). -spec dot(vec2(), vec2()) -> float(). dot(A, B) -> (erlang:element(2, A) * erlang:element(2, B)) + (erlang:element(3, A) * erlang:element( 3, B )). -file("src/viva_math/vec2.gleam", 46). ?DOC(" 2-D \"cross\" returns the z-component of the 3-D cross product.\n"). -spec cross(vec2(), vec2()) -> float(). cross(A, B) -> (erlang:element(2, A) * erlang:element(3, B)) - (erlang:element(3, A) * erlang:element( 2, B )). -file("src/viva_math/vec2.gleam", 50). -spec length_squared(vec2()) -> float(). length_squared(V) -> dot(V, V). -file("src/viva_math/vec2.gleam", 55). ?DOC(" Length √(x² + y²) — uses `hypot` to avoid overflow/underflow at extreme scales.\n"). -spec length(vec2()) -> float(). length(V) -> viva_math@scalar:hypot(erlang:element(2, V), erlang:element(3, V)). -file("src/viva_math/vec2.gleam", 59). -spec distance(vec2(), vec2()) -> float(). distance(A, B) -> length(sub(A, B)). -file("src/viva_math/vec2.gleam", 63). -spec normalize(vec2()) -> vec2(). normalize(V) -> L = length(V), case L =:= +0.0 of true -> zero(); false -> {vec2, case L of +0.0 -> +0.0; -0.0 -> -0.0; Gleam@denominator -> erlang:element(2, V) / Gleam@denominator end, case L of +0.0 -> +0.0; -0.0 -> -0.0; Gleam@denominator@1 -> erlang:element(3, V) / Gleam@denominator@1 end} end. -file("src/viva_math/vec2.gleam", 71). -spec lerp(vec2(), vec2(), float()) -> vec2(). lerp(A, B, T) -> {vec2, viva_math@scalar:lerp(erlang:element(2, A), erlang:element(2, B), T), viva_math@scalar:lerp(erlang:element(3, A), erlang:element(3, B), T)}. -file("src/viva_math/vec2.gleam", 75). -spec clamp(vec2(), float(), float()) -> vec2(). clamp(V, Lo, Hi) -> {vec2, viva_math@scalar:clamp(erlang:element(2, V), Lo, Hi), viva_math@scalar:clamp(erlang:element(3, V), Lo, Hi)}. -file("src/viva_math/vec2.gleam", 80). ?DOC(" Rotate `v` by `theta` radians around the origin.\n"). -spec rotate(vec2(), float()) -> vec2(). rotate(V, Theta) -> C = math:cos(Theta), S = math:sin(Theta), {vec2, (erlang:element(2, V) * C) - (erlang:element(3, V) * S), (erlang:element(2, V) * S) + (erlang:element(3, V) * C)}. -file("src/viva_math/vec2.gleam", 87). ?DOC(" Perpendicular vector (90° counter-clockwise rotation).\n"). -spec perpendicular(vec2()) -> vec2(). perpendicular(V) -> {vec2, +0.0 - erlang:element(3, V), erlang:element(2, V)}. -file("src/viva_math/vec2.gleam", 92). ?DOC(" Angle in radians of `v` relative to the positive x-axis. Range (-π, π].\n"). -spec angle(vec2()) -> float(). angle(V) -> math:atan2(erlang:element(3, V), erlang:element(2, V)). -file("src/viva_math/vec2.gleam", 97). ?DOC(" Component-wise approximate equality.\n"). -spec is_close(vec2(), vec2(), float()) -> boolean(). is_close(A, B, Tol) -> (gleam@float:absolute_value(erlang:element(2, A) - erlang:element(2, B)) =< Tol) andalso (gleam@float:absolute_value( erlang:element(3, A) - erlang:element(3, B) ) =< Tol).