Trigonometric Functions
Mix.install([
{:kino, "~> 0.14.2"}
])
Introduction
Trigonometric functions are provided by the Erlang :math module. These map between an angle of a right-angled triangle and the ratios of two side lengths. Specifically, in this workbook we explore the sine and cosine functions. They operate on angles measured in radians. An angle of $360^\circ$ corresponds to $2\cdot \pi$ radians.
References:
Visualization
defmodule Visualization do
@dim 256
@r (@dim*0.7)
defp deg2rad(degrees), do: 2*:math.pi*degrees/360
def produce_coordinate_system() do
style = "stroke-width=\"4\" stroke=\"black\" stroke-opacity=\"0.1\""
"""
"""
end
def produce_unit_circle() do
"""
"""
end
def produce_hand(x, y) do
"""
"""
end
def produce_decoration(a, x, y) do
{xlabel_offset, xlabel_baseline} =
if y<0 do
{20, "auto"}
else
{-20, "hanging"}
end
{ylabel_offset, ylabel_anchor} =
if x<0 do
{10, "start"}
else
{-10, "end"}
end
deg = a |> :erlang.float_to_binary([decimals: 0])
line_props = "stroke-width=\"2\" stroke=\"orange\" stroke-dasharray=\"5,5\""
"""
cos(#{deg}°) = #{x |> :erlang.float_to_binary([decimals: 2])}
sin(#{deg}°) = #{y |> :erlang.float_to_binary([decimals: 2])}
"""
end
def produce_angle(deg, rad) do
x = 1.35*@r*0.5*:math.cos(rad/2)
y = 1.35*@r*0.5*:math.sin(rad/2) * -1
direction = if deg<180 do 0 else 1 end
endx = @r*0.5*:math.cos(rad)
endy = @r*0.5*:math.sin(rad) * -1
"""
α = #{deg |> :erlang.float_to_binary([decimals: 0])}°
"""
end
def update_angle(angle, frame) do
a = deg2rad(angle)
x = :math.cos(a)
y = :math.sin(a) * -1
coordinate_lines = produce_coordinate_system()
circle_lines = produce_unit_circle()
hand_lines = produce_hand(x, y)
decoration_lines = produce_decoration(angle, x, y)
angle_lines = produce_angle(angle, a)
svg_kino =
"""
#{circle_lines}
#{hand_lines}
#{decoration_lines}
#{coordinate_lines}
#{angle_lines}
"""
|> Kino.Image.new(:svg)
Kino.Frame.render(frame, svg_kino)
end
end
Interface
kino = Kino.Input.range("Pick an angle:", min: 0, max: 360, default: 34, debounce: 1)
frame = Kino.Frame.new() |> Kino.render()
nil
Kino.listen(kino, fn event ->
Visualization.update_angle(event.value, frame)
end)