Guess who can draw arcs!
This commit is contained in:
parent
f09bf246d8
commit
a82804685b
4 changed files with 93 additions and 0 deletions
41
lib/vivid/arc.ex
Normal file
41
lib/vivid/arc.ex
Normal 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
|
44
lib/vivid/rasterize/arc.ex
Normal file
44
lib/vivid/rasterize/arc.ex
Normal 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
4
test/vivid/arc_test.exs
Normal file
|
@ -0,0 +1,4 @@
|
|||
defmodule Vivid.ArcTest do
|
||||
use ExUnit.Case
|
||||
doctest Vivid.Arc
|
||||
end
|
4
test/vivid/rasterize/arc_test.exs
Normal file
4
test/vivid/rasterize/arc_test.exs
Normal file
|
@ -0,0 +1,4 @@
|
|||
defmodule Vivid.Rasterize.ArcTest do
|
||||
use ExUnit.Case
|
||||
doctest Vivid.Rasterize.Vivid.Arc
|
||||
end
|
Loading…
Reference in a new issue