module Brillo.Data.Picture (
  Picture (..),
  Point,
  Vector,
  Path,

  -- * Compound shapes
  lineLoop,
  lineLoopAliased,
  circleSolid,
  circleSolidAliased,
  arcSolid,
  arcSolidAliased,
  sectorWire,
  sectorWireAliased,
  rectanglePath,
  rectangleWire,
  rectangleWireAliased,
  rectangleSolid,
  rectangleSolidAliased,
  rectangleUpperPath,
  rectangleUpperWire,
  rectangleUpperWireAliased,
  rectangleUpperSolid,
  rectangleUpperSolidAliased,
)
where

import Brillo.Geometry.Angle
import Brillo.Rendering


-- Shapes ---------------------------------------------------------------------

-- | A closed loop along a path, drawn with anti-aliasing.
lineLoop :: Path -> Picture
lineLoop :: Path -> Picture
lineLoop [] = Path -> Picture
Line []
lineLoop (Point
x : Path
xs) = Path -> Picture
Line ((Point
x Point -> Path -> Path
forall a. a -> [a] -> [a]
: Path
xs) Path -> Path -> Path
forall a. [a] -> [a] -> [a]
++ [Point
x])


-- | A closed loop along a path, drawn without anti-aliasing.
lineLoopAliased :: Path -> Picture
lineLoopAliased :: Path -> Picture
lineLoopAliased [] = Path -> Picture
LineAliased []
lineLoopAliased (Point
x : Path
xs) = Path -> Picture
LineAliased ((Point
x Point -> Path -> Path
forall a. a -> [a] -> [a]
: Path
xs) Path -> Path -> Path
forall a. [a] -> [a] -> [a]
++ [Point
x])


-- Circles and Arcs -----------------------------------------------------------

-- | A solid circle with the given radius, drawn with anti-aliasing.
circleSolid :: Float -> Picture
circleSolid :: Float -> Picture
circleSolid Float
r =
  Float -> Float -> Picture
ThickCircle (Float
r Float -> Float -> Float
forall a. Fractional a => a -> a -> a
/ Float
2) Float
r


-- | A solid circle with the given radius, drawn without anti-aliasing.
circleSolidAliased :: Float -> Picture
circleSolidAliased :: Float -> Picture
circleSolidAliased Float
r =
  Float -> Float -> Picture
ThickCircleAliased (Float
r Float -> Float -> Float
forall a. Fractional a => a -> a -> a
/ Float
2) Float
r


-- | A solid arc, drawn counter-clockwise between two angles (in degrees) at the given radius, with anti-aliasing.
arcSolid :: Float -> Float -> Float -> Picture
arcSolid :: Float -> Float -> Float -> Picture
arcSolid Float
a1 Float
a2 Float
r =
  Float -> Float -> Float -> Float -> Picture
ThickArc Float
a1 Float
a2 (Float
r Float -> Float -> Float
forall a. Fractional a => a -> a -> a
/ Float
2) Float
r


-- | A solid arc, drawn counter-clockwise between two angles (in degrees) at the given radius, without anti-aliasing.
arcSolidAliased :: Float -> Float -> Float -> Picture
arcSolidAliased :: Float -> Float -> Float -> Picture
arcSolidAliased Float
a1 Float
a2 Float
r =
  Float -> Float -> Float -> Float -> Picture
ThickArcAliased Float
a1 Float
a2 (Float
r Float -> Float -> Float
forall a. Fractional a => a -> a -> a
/ Float
2) Float
r


{-| A wireframe sector of a circle, drawn with anti-aliasing.
  An arc is draw counter-clockwise from the first to the second angle (in degrees) at
  the given radius. Lines are drawn from the origin to the ends of the arc.
-}

---
--   NOTE: We take the absolute value of the radius incase it's negative.
--   It would also make sense to draw the sector flipped around the
--   origin, but I think taking the absolute value will be less surprising
--   for the user.
--
sectorWire :: Float -> Float -> Float -> Picture
sectorWire :: Float -> Float -> Float -> Picture
sectorWire Float
a1 Float
a2 Float
r_ =
  let r :: Float
r = Float -> Float
forall a. Num a => a -> a
abs Float
r_
  in  [Picture] -> Picture
Pictures
        [ Float -> Float -> Float -> Picture
Arc Float
a1 Float
a2 Float
r
        , Path -> Picture
Line [(Float
0, Float
0), (Float
r Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float -> Float
forall a. Floating a => a -> a
cos (Float -> Float
degToRad Float
a1), Float
r Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float -> Float
forall a. Floating a => a -> a
sin (Float -> Float
degToRad Float
a1))]
        , Path -> Picture
Line [(Float
0, Float
0), (Float
r Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float -> Float
forall a. Floating a => a -> a
cos (Float -> Float
degToRad Float
a2), Float
r Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float -> Float
forall a. Floating a => a -> a
sin (Float -> Float
degToRad Float
a2))]
        ]


{-| A wireframe sector of a circle, drawn without anti-aliasing.
  An arc is draw counter-clockwise from the first to the second angle (in degrees) at
  the given radius. Lines are drawn from the origin to the ends of the arc.
-}
sectorWireAliased :: Float -> Float -> Float -> Picture
sectorWireAliased :: Float -> Float -> Float -> Picture
sectorWireAliased Float
a1 Float
a2 Float
r_ =
  let r :: Float
r = Float -> Float
forall a. Num a => a -> a
abs Float
r_
  in  [Picture] -> Picture
Pictures
        [ Float -> Float -> Float -> Picture
ArcAliased Float
a1 Float
a2 Float
r
        , Path -> Picture
LineAliased [(Float
0, Float
0), (Float
r Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float -> Float
forall a. Floating a => a -> a
cos (Float -> Float
degToRad Float
a1), Float
r Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float -> Float
forall a. Floating a => a -> a
sin (Float -> Float
degToRad Float
a1))]
        , Path -> Picture
LineAliased [(Float
0, Float
0), (Float
r Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float -> Float
forall a. Floating a => a -> a
cos (Float -> Float
degToRad Float
a2), Float
r Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float -> Float
forall a. Floating a => a -> a
sin (Float -> Float
degToRad Float
a2))]
        ]


-- Rectangles -----------------------------------------------------------------
-- NOTE: Only the first of these rectangle functions has haddocks on the
--       arguments to reduce the amount of noise in the extracted docs.

-- | A path representing a rectangle centered about the origin
rectanglePath ::
  -- | width of rectangle
  Float ->
  -- | height of rectangle
  Float ->
  Path
rectanglePath :: Float -> Float -> Path
rectanglePath Float
sizeX Float
sizeY =
  let sx :: Float
sx = Float
sizeX Float -> Float -> Float
forall a. Fractional a => a -> a -> a
/ Float
2
      sy :: Float
sy = Float
sizeY Float -> Float -> Float
forall a. Fractional a => a -> a -> a
/ Float
2
  in  [(-Float
sx, -Float
sy), (-Float
sx, Float
sy), (Float
sx, Float
sy), (Float
sx, -Float
sy)]


-- | A wireframe rectangle centered about the origin, drawn with anti-aliasing.
rectangleWire :: Float -> Float -> Picture
rectangleWire :: Float -> Float -> Picture
rectangleWire Float
sizeX Float
sizeY =
  Path -> Picture
lineLoop (Path -> Picture) -> Path -> Picture
forall a b. (a -> b) -> a -> b
$ Float -> Float -> Path
rectanglePath Float
sizeX Float
sizeY


-- | A wireframe rectangle centered about the origin, drawn without anti-aliasing.
rectangleWireAliased :: Float -> Float -> Picture
rectangleWireAliased :: Float -> Float -> Picture
rectangleWireAliased Float
sizeX Float
sizeY =
  Path -> Picture
lineLoopAliased (Path -> Picture) -> Path -> Picture
forall a b. (a -> b) -> a -> b
$ Float -> Float -> Path
rectanglePath Float
sizeX Float
sizeY


-- | A wireframe rectangle in the y > 0 half of the x-y plane, drawn with anti-aliasing.
rectangleUpperWire :: Float -> Float -> Picture
rectangleUpperWire :: Float -> Float -> Picture
rectangleUpperWire Float
sizeX Float
sizeY =
  Path -> Picture
lineLoop (Path -> Picture) -> Path -> Picture
forall a b. (a -> b) -> a -> b
$ Float -> Float -> Path
rectangleUpperPath Float
sizeX Float
sizeY


-- | A wireframe rectangle in the y > 0 half of the x-y plane, drawn without anti-aliasing.
rectangleUpperWireAliased :: Float -> Float -> Picture
rectangleUpperWireAliased :: Float -> Float -> Picture
rectangleUpperWireAliased Float
sizeX Float
sizeY =
  Path -> Picture
lineLoopAliased (Path -> Picture) -> Path -> Picture
forall a b. (a -> b) -> a -> b
$ Float -> Float -> Path
rectangleUpperPath Float
sizeX Float
sizeY


-- | A path representing a rectangle in the y > 0 half of the x-y plane.
rectangleUpperPath :: Float -> Float -> Path
rectangleUpperPath :: Float -> Float -> Path
rectangleUpperPath Float
sizeX Float
sy =
  let sx :: Float
sx = Float
sizeX Float -> Float -> Float
forall a. Fractional a => a -> a -> a
/ Float
2
  in  [(-Float
sx, Float
0), (-Float
sx, Float
sy), (Float
sx, Float
sy), (Float
sx, Float
0)]


-- | A solid rectangle centered about the origin, drawn with anti-aliased edges.
rectangleSolid :: Float -> Float -> Picture
rectangleSolid :: Float -> Float -> Picture
rectangleSolid Float
sizeX Float
sizeY =
  Path -> Picture
Polygon (Path -> Picture) -> Path -> Picture
forall a b. (a -> b) -> a -> b
$ Float -> Float -> Path
rectanglePath Float
sizeX Float
sizeY


-- | A solid rectangle centered about the origin, drawn without anti-aliasing.
rectangleSolidAliased :: Float -> Float -> Picture
rectangleSolidAliased :: Float -> Float -> Picture
rectangleSolidAliased Float
sizeX Float
sizeY =
  Path -> Picture
PolygonAliased (Path -> Picture) -> Path -> Picture
forall a b. (a -> b) -> a -> b
$ Float -> Float -> Path
rectanglePath Float
sizeX Float
sizeY


-- | A solid rectangle in the y > 0 half of the x-y plane, drawn with anti-aliased edges.
rectangleUpperSolid :: Float -> Float -> Picture
rectangleUpperSolid :: Float -> Float -> Picture
rectangleUpperSolid Float
sizeX Float
sizeY =
  Path -> Picture
Polygon (Path -> Picture) -> Path -> Picture
forall a b. (a -> b) -> a -> b
$ Float -> Float -> Path
rectangleUpperPath Float
sizeX Float
sizeY


-- | A solid rectangle in the y > 0 half of the x-y plane, drawn without anti-aliasing.
rectangleUpperSolidAliased :: Float -> Float -> Picture
rectangleUpperSolidAliased :: Float -> Float -> Picture
rectangleUpperSolidAliased Float
sizeX Float
sizeY =
  Path -> Picture
PolygonAliased (Path -> Picture) -> Path -> Picture
forall a b. (a -> b) -> a -> b
$ Float -> Float -> Path
rectangleUpperPath Float
sizeX Float
sizeY