Current section
Files
Jump to
Current section
Files
lib/vivid/circle.ex
defmodule Vivid.Circle do
alias Vivid.{Circle, Point, Polygon}
defstruct ~w(center radius fill)a
import Vivid.Math
@moduledoc ~S"""
Represents a circle based on it's center point and radius.
## Example
iex> use Vivid
...> Circle.init(Point.init(10,10), 10)
...> |> to_string()
"@@@@@@@@@@@@@@@@@@@@@@@\n" <>
"@@@@@@@@ @@@@@@@@\n" <>
"@@@@@@ @@@@@@@ @@@@@@\n" <>
"@@@@@ @@@@@@@@@@@ @@@@@\n" <>
"@@@@ @@@@@@@@@@@@@ @@@@\n" <>
"@@@ @@@@@@@@@@@@@@@ @@@\n" <>
"@@ @@@@@@@@@@@@@@@@@ @@\n" <>
"@@ @@@@@@@@@@@@@@@@@ @@\n" <>
"@ @@@@@@@@@@@@@@@@@@@ @\n" <>
"@ @@@@@@@@@@@@@@@@@@@ @\n" <>
"@ @@@@@@@@@@@@@@@@@@@ @\n" <>
"@ @@@@@@@@@@@@@@@@@@@ @\n" <>
"@ @@@@@@@@@@@@@@@@@@@ @\n" <>
"@ @@@@@@@@@@@@@@@@@@@ @\n" <>
"@ @@@@@@@@@@@@@@@@@@@ @\n" <>
"@@ @@@@@@@@@@@@@@@@@ @@\n" <>
"@@ @@@@@@@@@@@@@@@@@ @@\n" <>
"@@@ @@@@@@@@@@@@@@@ @@@\n" <>
"@@@@ @@@@@@@@@@@@@ @@@@\n" <>
"@@@@@ @@@@@@@@@@@ @@@@@\n" <>
"@@@@@@ @@@@@@@ @@@@@@\n" <>
"@@@@@@@@ @@@@@@@@\n" <>
"@@@@@@@@@@@@@@@@@@@@@@@\n"
"""
@opaque t :: %Circle{center: Point.t, radius: number, fill: boolean}
@doc """
Creates a circle from a point in 2D space and a radius.
## Example
iex> Vivid.Circle.init(Vivid.Point.init(5,5), 4)
#Vivid.Circle<[center: #Vivid.Point<{5, 5}>, radius: 4]>
"""
@spec init(Point.t, number) :: Circle.t
def init(%Point{} = point, radius)
when is_number(radius) and radius > 0,
do: init(point, radius, false)
@doc false
@spec init(Point.t, number, boolean) :: Circle.t
def init(%Point{} = point, radius, fill)
when is_number(radius) and is_boolean(fill) and radius > 0
do
%Circle{
center: point,
radius: radius,
fill: fill
}
end
@doc """
Returns the radius of a circle.
## Example
iex> Vivid.Circle.init(Vivid.Point.init(5,5), 4)
...> |> Vivid.Circle.radius
4
"""
@spec radius(Cricle.t) :: number
def radius(%Circle{radius: r}), do: r
@doc """
Returns the center point of a circle.
## Example
iex> Vivid.Circle.init(Vivid.Point.init(5,5), 4)
...> |> Vivid.Circle.center
%Vivid.Point{x: 5, y: 5}
"""
@spec center(Circle.t) :: Point.t
def center(%Circle{center: point}), do: point
@doc """
Returns the circumference of a circle.
## Example
iex> Vivid.Circle.init(Vivid.Point.init(5,5), 4)
...> |> Vivid.Circle.circumference
25.132741228718345
"""
@spec circumference(Circle.t) :: number
def circumference(%Circle{radius: radius}), do: 2 * :math.pi * radius
@doc ~S"""
Convert the `circle` into a Polygon.
We convert a circle into a Polygon whenever we Transform or render it, so
sometimes it might be worth doing it yourself and specifying how many vertices
the polygon should have.
When unspecified `steps` is set to the diameter of the circle rounded to
the nearest integer.
## Examples
iex> use Vivid
...> Circle.init(Point.init(5,5), 5)
...> |> Circle.to_polygon
...> |> to_string
"@@@@@@@@@@@@@\n" <>
"@@@@ @@@@\n" <>
"@@@ @@@@@ @@@\n" <>
"@@ @@@@@@@ @@\n" <>
"@@ @@@@@@@ @@\n" <>
"@ @@@@@@@@@ @\n" <>
"@ @@@@@@@@@ @\n" <>
"@ @@@@@@@@@ @\n" <>
"@@ @@@@@@@ @@\n" <>
"@@ @@@@@@@ @@\n" <>
"@@@ @@@@@ @@@\n" <>
"@@@@ @@@@\n" <>
"@@@@@@@@@@@@@\n"
"""
@spec to_polygon(Circle.t) :: Polygon.t
def to_polygon(%Circle{radius: radius} = circle), do: to_polygon(circle, round(radius * 2))
@doc ~S"""
Convert the `circle` into a Polygon with a specific number of vertices.
We convert a circle into a Polygon whenever we Transform or render it, so
sometimes it might be worth doing it yourself and specifying how many vertices
the polygon should have.
## Examples
iex> use Vivid
...> Circle.init(Point.init(5,5), 5)
...> |> Circle.to_polygon(3)
...> |> to_string
"@@@@@@@@@@@\n" <>
"@ @@@@@@@@\n" <>
"@ @ @@@@@@\n" <>
"@ @@@ @@@@\n" <>
"@ @@@@@ @@\n" <>
"@ @@@@@@@ @\n" <>
"@ @@@@@ @@\n" <>
"@ @@@ @@@@\n" <>
"@ @@ @@@@@@\n" <>
"@ @@@@@@@\n" <>
"@ @@@@@@@@@\n" <>
"@@@@@@@@@@@\n"
"""
@spec to_polygon(Circle.t, number) :: Polygon.t
def to_polygon(%Circle{center: center, radius: radius, fill: fill}, steps) do
h = center |> Point.x
k = center |> Point.y
step_degree = 360 / steps
points = Enum.map(0..steps - 1, fn(step) ->
theta = step_degree * step
theta = degrees_to_radians(theta)
x = h + radius * cos(theta)
y = k - radius * sin(theta)
Point.init(x, y)
end)
points
|> Polygon.init(fill)
end
end