Guess who can draw arcs!

This commit is contained in:
James Harton 2016-12-22 15:11:24 +13:00
parent f09bf246d8
commit a82804685b
4 changed files with 93 additions and 0 deletions

41
lib/vivid/arc.ex Normal file
View file

@ -0,0 +1,41 @@
defmodule Vivid.Arc do
alias Vivid.{Arc, Point}
defstruct ~w(center radius start_angle range steps)a
@moduledoc """
This module represents an Arc, otherwise known as a circle segment.
"""
@doc ~S"""
Creates an Arc.
`center` is a Point definining the center point of the arc's parent circle.
`radius` is the radius of the parent circle.
`start_angle` is the angle at which to start drawing the arc, `0` is vertical.
`range` is the number of degrees to draw the arc.
`steps` the arc is drawn by dividing it into a number of lines. Defaults to 12.
iex> Vivid.Arc.init(Vivid.Point.init(5,5), 4, 45, 15)
%Vivid.Arc{
center: %Vivid.Point{x: 5, y: 5},
radius: 4,
start_angle: 45,
range: 15,
steps: 12
}
"""
def init(%Point{}=center, radius, start_angle, range, steps \\ 12)
when is_number(radius)
and is_number(start_angle)
and is_number(range)
and is_number(steps)
do
%Vivid.Arc{
center: center,
radius: radius,
start_angle: start_angle,
range: range,
steps: steps
}
end
end

View file

@ -0,0 +1,44 @@
defimpl Vivid.Rasterize, for: Vivid.Arc do
import :math, only: [cos: 1, sin: 1, pi: 0]
alias Vivid.{Rasterize, Arc, Path, Point}
@moduledoc """
Rasterizes an Arc.
"""
@doc ~S"""
Convert an Arc into a rasterized points.
## Example
iex> Vivid.Arc.init(Vivid.Point.init(5,5), 5, 270, 90, 3)
...> |> Vivid.Rasterize.rasterize
MapSet.new([
%Vivid.Point{x: 0, y: 5}, %Vivid.Point{x: 1, y: 3},
%Vivid.Point{x: 1, y: 4}, %Vivid.Point{x: 2, y: 2},
%Vivid.Point{x: 3, y: 1}, %Vivid.Point{x: 4, y: 1},
%Vivid.Point{x: 5, y: 0}
])
"""
def rasterize(%Arc{center: center, radius: radius, start_angle: start_angle, range: range, steps: steps}) do
h = center |> Point.x
k = center |> Point.y
step_degree = range / steps
start_angle = start_angle - 180
Enum.map(0..steps, fn(step) ->
theta = (step_degree * step) + start_angle
theta = degrees_to_radians(theta)
x = round(h + radius * cos(theta))
y = round(k - radius * sin(theta))
Point.init(x, y)
end)
|> Path.init
|> Rasterize.rasterize
end
defp degrees_to_radians(degrees), do: degrees / 360.0 * 2.0 * pi
end

4
test/vivid/arc_test.exs Normal file
View file

@ -0,0 +1,4 @@
defmodule Vivid.ArcTest do
use ExUnit.Case
doctest Vivid.Arc
end

View file

@ -0,0 +1,4 @@
defmodule Vivid.Rasterize.ArcTest do
use ExUnit.Case
doctest Vivid.Rasterize.Vivid.Arc
end