{-# OPTIONS_GHC -Wno-duplicate-exports #-}
module Draw (
render
, CoordinateSystem(..)
, coordinateSystem
, haddockRender
, moveToVec
, lineToVec
, Sketch(..)
, Arrow(..)
, ArrowSpec(..)
, Circle(..)
, Cross(..)
, PolyBezier(..)
, arcSketch
, arcSketchNegative
, Colour, Color
, AlphaColour, AlphaColor
, CairoColor(..)
, module Draw.Color
, module Draw.Color.Schemes.Discrete
, module Draw.Color.Schemes.Continuous
, withOperator
, cairoScope
, grouped
, cartesianCoordinateSystem
, CartesianParams(..)
, radialCoordinateSystem
, PolarParams(..)
, fromCairoMatrix
, toCairoMatrix
, module Draw.Text
, for_
, module Data.Foldable
, module Data.Default.Class
) where
import Control.Monad
import qualified Data.ByteString.Lazy as BSL
import Data.Default.Class
import Data.Foldable
import Data.Int
import Data.List
import Graphics.Rendering.Cairo as C hiding (x, y)
import Graphics.Rendering.Cairo.Matrix (Matrix (..))
import System.Directory
import System.FilePath
import Text.Printf
import Data.Crc32
import Draw.Color
import Draw.Color.Schemes.Continuous
import Draw.Color.Schemes.Discrete
import Draw.NormalizeSvg
import Draw.Text
import Geometry as G
withSurface
:: OutputFormat
-> FilePath
-> Int
-> Int
-> (Surface -> IO a)
-> IO a
withSurface :: forall a.
OutputFormat -> String -> Int -> Int -> (Surface -> IO a) -> IO a
withSurface OutputFormat
PNG String
file Int
w Int
h Surface -> IO a
action = Format -> Int -> Int -> (Surface -> IO a) -> IO a
forall a. Format -> Int -> Int -> (Surface -> IO a) -> IO a
withImageSurface Format
FormatARGB32 Int
w Int
h ((Surface -> IO a) -> IO a) -> (Surface -> IO a) -> IO a
forall a b. (a -> b) -> a -> b
$ \Surface
surface -> do
a
result <- Surface -> IO a
action Surface
surface
Surface -> String -> IO ()
surfaceWriteToPNG Surface
surface String
file
a -> IO a
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure a
result
withSurface OutputFormat
SVG String
file Int
w Int
h Surface -> IO a
draw = String -> Double -> Double -> (Surface -> IO a) -> IO a
forall a. String -> Double -> Double -> (Surface -> IO a) -> IO a
withSVGSurface String
file (Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
w) (Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
h) ((Surface -> IO a) -> IO a) -> (Surface -> IO a) -> IO a
forall a b. (a -> b) -> a -> b
$ \Surface
surface -> do
Surface -> SvgUnit -> IO ()
forall (m :: * -> *). MonadIO m => Surface -> SvgUnit -> m ()
svgSurfaceSetDocumentUnit Surface
surface SvgUnit
SvgUnitPx
Surface -> IO a
draw Surface
surface
data OutputFormat = PNG | SVG
fromExtension :: String -> OutputFormat
fromExtension :: String -> OutputFormat
fromExtension String
filePath
| String
".png" String -> String -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`isSuffixOf` String
filePath = OutputFormat
PNG
| String
".svg" String -> String -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`isSuffixOf` String
filePath = OutputFormat
SVG
| Bool
otherwise = String -> OutputFormat
forall a. HasCallStack => String -> a
error (String
"Unknown file extension: " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
filePath String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
", expecting .png or .svg")
render
:: FilePath
-> Int
-> Int
-> Render ()
-> IO ()
render :: String -> Int -> Int -> Render () -> IO ()
render String
filepath Int
w Int
h Render ()
actions = do
Bool -> String -> IO ()
createDirectoryIfMissing Bool
True (String -> String
takeDirectory String
filepath String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"/")
OutputFormat -> String -> Int -> Int -> (Surface -> IO ()) -> IO ()
forall a.
OutputFormat -> String -> Int -> Int -> (Surface -> IO a) -> IO a
withSurface (String -> OutputFormat
fromExtension String
filepath) String
filepath Int
w Int
h (\Surface
surface -> Surface -> Render () -> IO ()
forall (m :: * -> *) a. MonadIO m => Surface -> Render a -> m a
renderWith Surface
surface Render ()
actions)
data CoordinateSystem
= CairoStandard_ZeroTopLeft_XRight_YDown
| MathStandard_ZeroBottomLeft_XRight_YUp Double
| MathStandard_ZeroCenter_XRight_YUp Double Double
deriving (CoordinateSystem -> CoordinateSystem -> Bool
(CoordinateSystem -> CoordinateSystem -> Bool)
-> (CoordinateSystem -> CoordinateSystem -> Bool)
-> Eq CoordinateSystem
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: CoordinateSystem -> CoordinateSystem -> Bool
== :: CoordinateSystem -> CoordinateSystem -> Bool
$c/= :: CoordinateSystem -> CoordinateSystem -> Bool
/= :: CoordinateSystem -> CoordinateSystem -> Bool
Eq, Eq CoordinateSystem
Eq CoordinateSystem
-> (CoordinateSystem -> CoordinateSystem -> Ordering)
-> (CoordinateSystem -> CoordinateSystem -> Bool)
-> (CoordinateSystem -> CoordinateSystem -> Bool)
-> (CoordinateSystem -> CoordinateSystem -> Bool)
-> (CoordinateSystem -> CoordinateSystem -> Bool)
-> (CoordinateSystem -> CoordinateSystem -> CoordinateSystem)
-> (CoordinateSystem -> CoordinateSystem -> CoordinateSystem)
-> Ord CoordinateSystem
CoordinateSystem -> CoordinateSystem -> Bool
CoordinateSystem -> CoordinateSystem -> Ordering
CoordinateSystem -> CoordinateSystem -> CoordinateSystem
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: CoordinateSystem -> CoordinateSystem -> Ordering
compare :: CoordinateSystem -> CoordinateSystem -> Ordering
$c< :: CoordinateSystem -> CoordinateSystem -> Bool
< :: CoordinateSystem -> CoordinateSystem -> Bool
$c<= :: CoordinateSystem -> CoordinateSystem -> Bool
<= :: CoordinateSystem -> CoordinateSystem -> Bool
$c> :: CoordinateSystem -> CoordinateSystem -> Bool
> :: CoordinateSystem -> CoordinateSystem -> Bool
$c>= :: CoordinateSystem -> CoordinateSystem -> Bool
>= :: CoordinateSystem -> CoordinateSystem -> Bool
$cmax :: CoordinateSystem -> CoordinateSystem -> CoordinateSystem
max :: CoordinateSystem -> CoordinateSystem -> CoordinateSystem
$cmin :: CoordinateSystem -> CoordinateSystem -> CoordinateSystem
min :: CoordinateSystem -> CoordinateSystem -> CoordinateSystem
Ord, Int -> CoordinateSystem -> String -> String
[CoordinateSystem] -> String -> String
CoordinateSystem -> String
(Int -> CoordinateSystem -> String -> String)
-> (CoordinateSystem -> String)
-> ([CoordinateSystem] -> String -> String)
-> Show CoordinateSystem
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
$cshowsPrec :: Int -> CoordinateSystem -> String -> String
showsPrec :: Int -> CoordinateSystem -> String -> String
$cshow :: CoordinateSystem -> String
show :: CoordinateSystem -> String
$cshowList :: [CoordinateSystem] -> String -> String
showList :: [CoordinateSystem] -> String -> String
Show)
instance Default CoordinateSystem where
def :: CoordinateSystem
def = CoordinateSystem
CairoStandard_ZeroTopLeft_XRight_YDown
coordinateSystem :: CoordinateSystem -> Render ()
coordinateSystem :: CoordinateSystem -> Render ()
coordinateSystem CoordinateSystem
cosy = do
Render ()
C.identityMatrix
case CoordinateSystem
cosy of
CoordinateSystem
CairoStandard_ZeroTopLeft_XRight_YDown -> () -> Render ()
forall a. a -> Render a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
MathStandard_ZeroBottomLeft_XRight_YUp Double
height -> do
Double -> Double -> Render ()
C.translate Double
0 Double
height
Double -> Double -> Render ()
C.scale Double
1 (-Double
1)
MathStandard_ZeroCenter_XRight_YUp Double
width Double
height -> do
Double -> Double -> Render ()
C.translate Double
0 Double
height
Double -> Double -> Render ()
C.scale Double
1 (-Double
1)
Double -> Double -> Render ()
C.translate (Double
widthDouble -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
2) (Double
heightDouble -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
2)
haddockRender
:: FilePath
-> Int
-> Int
-> (Vec2 -> Render ())
-> IO ()
haddockRender :: String -> Int -> Int -> (Vec2 -> Render ()) -> IO ()
haddockRender String
filename Int
w Int
h Vec2 -> Render ()
actions = do
let filepath :: String
filepath = String
"docs/haddock/" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
filename
String -> Int -> Int -> Render () -> IO ()
render String
filepath Int
w Int
h (Render () -> IO ()) -> Render () -> IO ()
forall a b. (a -> b) -> a -> b
$ do
CoordinateSystem -> Render ()
coordinateSystem (Double -> CoordinateSystem
MathStandard_ZeroBottomLeft_XRight_YUp (Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
h))
Int -> Int -> Render ()
haddockGrid Int
w Int
h
do
Double -> Render ()
C.setLineWidth Double
1.5
Color Double -> Render ()
forall color. CairoColor color => color -> Render ()
setColor (Int -> Color Double
mma Int
0)
[Double] -> Double -> Render ()
C.setDash [] Double
0
Double -> Render ()
C.setTolerance Double
0.1
Antialias -> Render ()
C.setAntialias Antialias
C.AntialiasDefault
LineCap -> Render ()
C.setLineCap LineCap
C.LineCapRound
LineJoin -> Render ()
C.setLineJoin LineJoin
C.LineJoinRound
FillRule -> Render ()
C.setFillRule FillRule
C.FillRuleWinding
Matrix
matrix <- Render Matrix -> Render Matrix
forall a. Render a -> Render a
cairoScope (Render Matrix -> Render Matrix) -> Render Matrix -> Render Matrix
forall a b. (a -> b) -> a -> b
$ do
Vec2 -> Render ()
actions (Double -> Double -> Vec2
Vec2 (Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
w) (Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
h))
Render Matrix
getMatrix
Render () -> Render ()
forall a. Render a -> Render a
cairoScope (Render () -> Render ()) -> Render () -> Render ()
forall a b. (a -> b) -> a -> b
$ do
Matrix -> Render ()
setMatrix Matrix
matrix
Vec2 -> Double -> Render ()
haddockAxes (Double -> Double -> Vec2
Vec2 Double
5 Double
5) Double
15
String -> IO ()
normalizeSvgFile String
filepath
String -> IO ()
haddockPrintInfo String
filepath
haddockGrid :: Int -> Int -> Render ()
haddockGrid :: Int -> Int -> Render ()
haddockGrid Int
w Int
h = Render () -> Render () -> Render ()
forall after a. Render after -> Render a -> Render a
grouped (Double -> Render ()
paintWithAlpha Double
0.1) (Render () -> Render ()) -> Render () -> Render ()
forall a b. (a -> b) -> a -> b
$ do
let i :: Int -> Double
i = Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral
xLine :: Int -> Render ()
xLine Int
y = Line -> Render ()
forall a. Sketch a => a -> Render ()
sketch (Vec2 -> Vec2 -> Line
Line (Double -> Double -> Vec2
Vec2 Double
0 (Int -> Double
i Int
y)) (Double -> Double -> Vec2
Vec2 (Int -> Double
i Int
w) (Int -> Double
i Int
y)))
yLine :: Int -> Render ()
yLine Int
x = Line -> Render ()
forall a. Sketch a => a -> Render ()
sketch (Vec2 -> Vec2 -> Line
Line (Double -> Double -> Vec2
Vec2 (Int -> Double
i Int
x) Double
0) (Double -> Double -> Vec2
Vec2 (Int -> Double
i Int
x) (Int -> Double
i Int
h)))
[Double] -> Double -> Render ()
setDash [Double
5,Double
5] Double
2.5
[Int] -> (Int -> Render ()) -> Render ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ [Int
0, Int
10 .. Int
h] Int -> Render ()
xLine
[Int] -> (Int -> Render ()) -> Render ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ [Int
0, Int
10 .. Int
w] Int -> Render ()
yLine
Double -> Render ()
setLineWidth Double
0.7
Render ()
stroke
haddockAxes :: Vec2 -> Double -> Render ()
haddockAxes :: Vec2 -> Double -> Render ()
haddockAxes Vec2
start Double
len = Render () -> Render () -> Render ()
forall after a. Render after -> Render a -> Render a
grouped (Double -> Render ()
paintWithAlpha Double
0.5) (Render () -> Render ()) -> Render () -> Render ()
forall a b. (a -> b) -> a -> b
$ do
Double
yDirection <- do
Matrix Double
_xx Double
_yx Double
_xy Double
yy Double
_x0 Double
_y0 <- Render Matrix
C.getMatrix
Double -> Render Double
forall a. a -> Render a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Double
yy
Double -> Render ()
C.setLineWidth Double
0.5
Colour Integer -> Render ()
forall color. CairoColor color => color -> Render ()
setColor Colour Integer
forall a. Num a => Colour a
black
[Arrow] -> Render ()
forall a. Sketch a => a -> Render ()
sketch [Arrow]
arrows
[Line] -> Render ()
forall a. Sketch a => a -> Render ()
sketch [Line]
xSymbol
[Line] -> Render ()
forall a. Sketch a => a -> Render ()
sketch (Double -> [Line]
forall {p}. (Ord p, Num p) => p -> [Line]
ySymbol Double
yDirection)
Render ()
stroke
where
arrows :: [Arrow]
arrows =
let arrowSpec :: ArrowSpec
arrowSpec = ArrowSpec
forall a. Default a => a
def { _arrowheadSize :: Double
_arrowheadSize = Double
3 }
xLine :: Line
xLine = Vec2 -> Vec2 -> Line
Line Vec2
forall v. VectorSpace v => v
zero (Double -> Double -> Vec2
Vec2 Double
len Double
0)
yLine :: Line
yLine = Vec2 -> Vec2 -> Line
Line Vec2
forall v. VectorSpace v => v
zero (Double -> Double -> Vec2
Vec2 Double
0 Double
len)
in [Line -> ArrowSpec -> Arrow
Arrow (Transformation -> Line -> Line
forall geo. Transform geo => Transformation -> geo -> geo
G.transform (Vec2 -> Transformation
G.translate Vec2
start) Line
line) ArrowSpec
arrowSpec | Line
line <- [Line
xLine, Line
yLine]]
xSymbol :: [Line]
xSymbol =
let angle :: Angle
angle = Double -> Angle
deg Double
55
lx :: Double
lx = Double
2.6
x' :: [Line]
x' = [ Line -> Line
centerLine (Vec2 -> Angle -> Double -> Line
angledLine Vec2
forall v. VectorSpace v => v
zero Angle
angle Double
lx)
, Line -> Line
centerLine (Vec2 -> Angle -> Double -> Line
angledLine Vec2
forall v. VectorSpace v => v
zero (Double -> Angle
deg Double
180 Angle -> Angle -> Angle
forall v. VectorSpace v => v -> v -> v
-. Angle
angle) Double
lx)
]
in Transformation -> [Line] -> [Line]
forall geo. Transform geo => Transformation -> geo -> geo
G.transform (Vec2 -> Transformation
G.translate (Vec2
start Vec2 -> Vec2 -> Vec2
forall v. VectorSpace v => v -> v -> v
+. Double -> Double -> Vec2
Vec2 (Double
lenDouble -> Double -> Double
forall a. Num a => a -> a -> a
+Double
5) Double
0) Transformation -> Transformation -> Transformation
forall a. Semigroup a => a -> a -> a
<> Double -> Transformation
G.scale Double
2) [Line]
x'
ySymbol :: p -> [Line]
ySymbol p
yDirection =
let angle :: Angle
angle = Double -> Angle
deg Double
55
ly :: Double
ly = Double
3
y' :: [Line]
y' = [ Line -> Line
centerLine (Vec2 -> Angle -> Double -> Line
angledLine Vec2
forall v. VectorSpace v => v
zero Angle
angle Double
ly)
, Vec2 -> Angle -> Double -> Line
angledLine Vec2
forall v. VectorSpace v => v
zero (Double -> Angle
deg Double
180 Angle -> Angle -> Angle
forall v. VectorSpace v => v -> v -> v
-. Angle
angle) (Double
lyDouble -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
2)
]
directionFlip :: Transformation
directionFlip | p
yDirection p -> p -> Bool
forall a. Ord a => a -> a -> Bool
< p
0 = Transformation
forall a. Monoid a => a
mempty
| Bool
otherwise = Transformation
mirrorYCoords
in Transformation -> [Line] -> [Line]
forall geo. Transform geo => Transformation -> geo -> geo
G.transform (Vec2 -> Transformation
G.translate (Vec2
start Vec2 -> Vec2 -> Vec2
forall v. VectorSpace v => v -> v -> v
+. Double -> Double -> Vec2
Vec2 Double
0 (Double
lenDouble -> Double -> Double
forall a. Num a => a -> a -> a
+Double
5)) Transformation -> Transformation -> Transformation
forall a. Semigroup a => a -> a -> a
<> Double -> Transformation
G.scale Double
2 Transformation -> Transformation -> Transformation
forall a. Semigroup a => a -> a -> a
<> Transformation
directionFlip) [Line]
y'
haddockPrintInfo :: FilePath -> IO ()
haddockPrintInfo :: String -> IO ()
haddockPrintInfo String
filepath = do
ByteString
contents <- String -> IO ByteString
BSL.readFile String
filepath
String -> String -> String -> IO ()
forall r. PrintfType r => String -> r
printf String
"Generated file: size %s, crc32: %s" (Int64 -> String
humanFilesize (ByteString -> Int64
BSL.length ByteString
contents)) (Crc32 -> String
forall a. Show a => a -> String
show (ByteString -> Crc32
crc32 ByteString
contents))
humanFilesize :: Int64 -> String
humanFilesize :: Int64 -> String
humanFilesize = [String] -> Int64 -> String
forall {t}.
(PrintfArg t, Show t, Integral t) =>
[String] -> t -> String
go [String]
suffixes
where
go :: [String] -> t -> String
go [] t
size = String -> t -> String
forall r. PrintfType r => String -> r
printf String
"Oh wow this file is %d byte large I ran out of suffixes" t
size
go (String
suffix:[String]
rest) t
size
| t
size t -> t -> Bool
forall a. Ord a => a -> a -> Bool
< t
1000 = t -> String
forall a. Show a => a -> String
show t
size String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
suffix
| Bool
otherwise = [String] -> t -> String
go [String]
rest (t
size t -> t -> t
forall a. Integral a => a -> a -> a
`div` t
1000)
suffixes :: [String]
suffixes = [String
"B", String
"KB", String
"MB", String
"GB", String
"TB", String
"PB"]
moveToVec :: Vec2 -> Render ()
moveToVec :: Vec2 -> Render ()
moveToVec (Vec2 Double
x Double
y) = Double -> Double -> Render ()
moveTo Double
x Double
y
lineToVec :: Vec2 -> Render ()
lineToVec :: Vec2 -> Render ()
lineToVec (Vec2 Double
x Double
y) = Double -> Double -> Render ()
lineTo Double
x Double
y
instance Sketch Bezier where
sketch :: Bezier -> Render ()
sketch (Bezier Vec2
start (Vec2 Double
x1 Double
y1) (Vec2 Double
x2 Double
y2) (Vec2 Double
x3 Double
y3)) = do
Vec2 -> Render ()
moveToVec Vec2
start
Double
-> Double -> Double -> Double -> Double -> Double -> Render ()
curveTo Double
x1 Double
y1 Double
x2 Double
y2 Double
x3 Double
y3
newtype PolyBezier f = PolyBezier (f Bezier)
instance Sequential f => Sketch (PolyBezier f) where
sketch :: PolyBezier f -> Render ()
sketch (PolyBezier f Bezier
xs) = [Bezier] -> Render ()
go (f Bezier -> [Bezier]
forall a. f a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList f Bezier
xs)
where
go :: [Bezier] -> Render ()
go [] = () -> Render ()
forall a. a -> Render a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
go ps :: [Bezier]
ps@(Bezier Vec2
start Vec2
_ Vec2
_ Vec2
_ : [Bezier]
_) = do
Vec2 -> Render ()
moveToVec Vec2
start
[Bezier] -> (Bezier -> Render ()) -> Render ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ [Bezier]
ps ((Bezier -> Render ()) -> Render ())
-> (Bezier -> Render ()) -> Render ()
forall a b. (a -> b) -> a -> b
$ \(Bezier Vec2
_ (Vec2 Double
x1 Double
y1) (Vec2 Double
x2 Double
y2) (Vec2 Double
x3 Double
y3)) -> Double
-> Double -> Double -> Double -> Double -> Double -> Render ()
curveTo Double
x1 Double
y1 Double
x2 Double
y2 Double
x3 Double
y3
data ArrowSpec = ArrowSpec
{ ArrowSpec -> Double
_arrowheadRelPos :: !Double
, ArrowSpec -> Double
_arrowheadSize :: !Double
, ArrowSpec -> Bool
_arrowDrawBody :: !Bool
, ArrowSpec -> Angle
_arrowheadAngle :: !Angle
, ArrowSpec -> Bool
_arrowheadDrawRight :: !Bool
, ArrowSpec -> Bool
_arrowheadDrawLeft :: !Bool
} deriving (ArrowSpec -> ArrowSpec -> Bool
(ArrowSpec -> ArrowSpec -> Bool)
-> (ArrowSpec -> ArrowSpec -> Bool) -> Eq ArrowSpec
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: ArrowSpec -> ArrowSpec -> Bool
== :: ArrowSpec -> ArrowSpec -> Bool
$c/= :: ArrowSpec -> ArrowSpec -> Bool
/= :: ArrowSpec -> ArrowSpec -> Bool
Eq, Int -> ArrowSpec -> String -> String
[ArrowSpec] -> String -> String
ArrowSpec -> String
(Int -> ArrowSpec -> String -> String)
-> (ArrowSpec -> String)
-> ([ArrowSpec] -> String -> String)
-> Show ArrowSpec
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
$cshowsPrec :: Int -> ArrowSpec -> String -> String
showsPrec :: Int -> ArrowSpec -> String -> String
$cshow :: ArrowSpec -> String
show :: ArrowSpec -> String
$cshowList :: [ArrowSpec] -> String -> String
showList :: [ArrowSpec] -> String -> String
Show)
instance Default ArrowSpec where
def :: ArrowSpec
def = ArrowSpec
{ _arrowheadRelPos :: Double
_arrowheadRelPos = Double
1
, _arrowheadSize :: Double
_arrowheadSize = Double
10
, _arrowDrawBody :: Bool
_arrowDrawBody = Bool
True
, _arrowheadAngle :: Angle
_arrowheadAngle = Double -> Angle
rad Double
0.5
, _arrowheadDrawRight :: Bool
_arrowheadDrawRight = Bool
True
, _arrowheadDrawLeft :: Bool
_arrowheadDrawLeft = Bool
True
}
data Arrow = Arrow !Line !ArrowSpec
deriving (Arrow -> Arrow -> Bool
(Arrow -> Arrow -> Bool) -> (Arrow -> Arrow -> Bool) -> Eq Arrow
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Arrow -> Arrow -> Bool
== :: Arrow -> Arrow -> Bool
$c/= :: Arrow -> Arrow -> Bool
/= :: Arrow -> Arrow -> Bool
Eq, Int -> Arrow -> String -> String
[Arrow] -> String -> String
Arrow -> String
(Int -> Arrow -> String -> String)
-> (Arrow -> String) -> ([Arrow] -> String -> String) -> Show Arrow
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
$cshowsPrec :: Int -> Arrow -> String -> String
showsPrec :: Int -> Arrow -> String -> String
$cshow :: Arrow -> String
show :: Arrow -> String
$cshowList :: [Arrow] -> String -> String
showList :: [Arrow] -> String -> String
Show)
instance Sketch Arrow where
sketch :: Arrow -> Render ()
sketch (Arrow Line
line ArrowSpec{Bool
Double
Angle
_arrowheadSize :: ArrowSpec -> Double
_arrowheadRelPos :: ArrowSpec -> Double
_arrowDrawBody :: ArrowSpec -> Bool
_arrowheadAngle :: ArrowSpec -> Angle
_arrowheadDrawRight :: ArrowSpec -> Bool
_arrowheadDrawLeft :: ArrowSpec -> Bool
_arrowheadRelPos :: Double
_arrowheadSize :: Double
_arrowDrawBody :: Bool
_arrowheadAngle :: Angle
_arrowheadDrawRight :: Bool
_arrowheadDrawLeft :: Bool
..}) = do
Bool -> Render () -> Render ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
_arrowDrawBody (Line -> Render ()
forall a. Sketch a => a -> Render ()
sketch Line
line)
let Line Vec2
start Vec2
end = Line
line
arrowTip :: Vec2
arrowTip = Vec2
start Vec2 -> Vec2 -> Vec2
forall v. VectorSpace v => v -> v -> v
+. (Double
_arrowheadRelPos Double -> Vec2 -> Vec2
forall v. VectorSpace v => Double -> v -> v
*. (Vec2
end Vec2 -> Vec2 -> Vec2
forall v. VectorSpace v => v -> v -> v
-. Vec2
start))
let arrowheadHalf :: (Angle -> Angle -> Angle) -> Line
arrowheadHalf Angle -> Angle -> Angle
(+-) = Vec2 -> Angle -> Double -> Line
angledLine Vec2
arrowTip (Line -> Angle
angleOfLine Line
line Angle -> Angle -> Angle
forall v. VectorSpace v => v -> v -> v
+. Double -> Angle
rad Double
forall a. Floating a => a
pi Angle -> Angle -> Angle
+- Angle
_arrowheadAngle) Double
_arrowheadSize
Line Vec2
_ Vec2
arrowLeftEnd = (Angle -> Angle -> Angle) -> Line
arrowheadHalf Angle -> Angle -> Angle
forall v. VectorSpace v => v -> v -> v
(+.)
Line Vec2
_ Vec2
arrowRightEnd = (Angle -> Angle -> Angle) -> Line
arrowheadHalf Angle -> Angle -> Angle
forall v. VectorSpace v => v -> v -> v
(-.)
case (Bool
_arrowheadDrawRight, Bool
_arrowheadDrawLeft) of
(Bool
True, Bool
True) -> do
Vec2 -> Render ()
moveToVec Vec2
arrowLeftEnd
Vec2 -> Render ()
lineToVec Vec2
arrowTip
Vec2 -> Render ()
lineToVec Vec2
arrowRightEnd
(Bool
False, Bool
True) -> do
Vec2 -> Render ()
moveToVec Vec2
arrowLeftEnd
Vec2 -> Render ()
lineToVec Vec2
arrowTip
(Bool
True, Bool
False) -> do
Vec2 -> Render ()
moveToVec Vec2
arrowRightEnd
Vec2 -> Render ()
lineToVec Vec2
arrowTip
(Bool
False, Bool
False) -> () -> Render ()
forall a. a -> Render a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
class Sketch a where
sketch :: a -> Render ()
instance (Sketch a, Sketch b) => Sketch (Either a b) where
sketch :: Either a b -> Render ()
sketch (Left a
l) = a -> Render ()
forall a. Sketch a => a -> Render ()
sketch a
l
sketch (Right b
r) = b -> Render ()
forall a. Sketch a => a -> Render ()
sketch b
r
instance (Sketch a, Sketch b) => Sketch (a,b) where
sketch :: (a, b) -> Render ()
sketch (a
a,b
b) = a -> Render ()
forall a. Sketch a => a -> Render ()
sketch a
a Render () -> Render () -> Render ()
forall after a. Render after -> Render a -> Render a
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> b -> Render ()
forall a. Sketch a => a -> Render ()
sketch b
b
instance (Sketch a, Sketch b, Sketch c) => Sketch (a,b,c) where
sketch :: (a, b, c) -> Render ()
sketch (a
a,b
b,c
c) = a -> Render ()
forall a. Sketch a => a -> Render ()
sketch a
a Render () -> Render () -> Render ()
forall after a. Render after -> Render a -> Render a
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> b -> Render ()
forall a. Sketch a => a -> Render ()
sketch b
b Render () -> Render () -> Render ()
forall after a. Render after -> Render a -> Render a
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> c -> Render ()
forall a. Sketch a => a -> Render ()
sketch c
c
instance (Sketch a, Sketch b, Sketch c, Sketch d) => Sketch (a,b,c,d) where
sketch :: (a, b, c, d) -> Render ()
sketch (a
a,b
b,c
c,d
d) = a -> Render ()
forall a. Sketch a => a -> Render ()
sketch a
a Render () -> Render () -> Render ()
forall after a. Render after -> Render a -> Render a
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> b -> Render ()
forall a. Sketch a => a -> Render ()
sketch b
b Render () -> Render () -> Render ()
forall after a. Render after -> Render a -> Render a
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> c -> Render ()
forall a. Sketch a => a -> Render ()
sketch c
c Render () -> Render () -> Render ()
forall after a. Render after -> Render a -> Render a
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> d -> Render ()
forall a. Sketch a => a -> Render ()
sketch d
d
instance (Sketch a, Sketch b, Sketch c, Sketch d, Sketch e) => Sketch (a,b,c,d,e) where
sketch :: (a, b, c, d, e) -> Render ()
sketch (a
a,b
b,c
c,d
d,e
e) = a -> Render ()
forall a. Sketch a => a -> Render ()
sketch a
a Render () -> Render () -> Render ()
forall after a. Render after -> Render a -> Render a
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> b -> Render ()
forall a. Sketch a => a -> Render ()
sketch b
b Render () -> Render () -> Render ()
forall after a. Render after -> Render a -> Render a
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> c -> Render ()
forall a. Sketch a => a -> Render ()
sketch c
c Render () -> Render () -> Render ()
forall after a. Render after -> Render a -> Render a
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> d -> Render ()
forall a. Sketch a => a -> Render ()
sketch d
d Render () -> Render () -> Render ()
forall after a. Render after -> Render a -> Render a
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> e -> Render ()
forall a. Sketch a => a -> Render ()
sketch e
e
instance Sketch a => Sketch [a] where
sketch :: [a] -> Render ()
sketch [a]
xs = [a] -> (a -> Render ()) -> Render ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ [a]
xs a -> Render ()
forall a. Sketch a => a -> Render ()
sketch
instance Sketch a => Sketch (Maybe a) where
sketch :: Maybe a -> Render ()
sketch Maybe a
xs = Maybe a -> (a -> Render ()) -> Render ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ Maybe a
xs a -> Render ()
forall a. Sketch a => a -> Render ()
sketch
instance Sketch Line where
sketch :: Line -> Render ()
sketch (Line Vec2
start Vec2
end) = do
Vec2 -> Render ()
moveToVec Vec2
start
Vec2 -> Render ()
lineToVec Vec2
end
instance Sketch Polyline where
sketch :: Polyline -> Render ()
sketch (Polyline [Vec2]
xs) = [Vec2] -> Render ()
go [Vec2]
xs
where
go :: [Vec2] -> Render ()
go [] = () -> Render ()
forall a. a -> Render a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
go (Vec2 Double
x0 Double
y0 : [Vec2]
vecs) = do
Double -> Double -> Render ()
moveTo Double
x0 Double
y0
[Vec2] -> (Vec2 -> Render ()) -> Render ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ [Vec2]
vecs (\(Vec2 Double
x Double
y) -> Double -> Double -> Render ()
lineTo Double
x Double
y)
instance Sketch Polygon where
sketch :: Polygon -> Render ()
sketch (Polygon []) = () -> Render ()
forall a. a -> Render a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
sketch (Polygon [Vec2]
xs) = Polyline -> Render ()
forall a. Sketch a => a -> Render ()
sketch ([Vec2] -> Polyline
Polyline [Vec2]
xs) Render () -> Render () -> Render ()
forall after a. Render after -> Render a -> Render a
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Render ()
closePath
instance Sketch Circle where
sketch :: Circle -> Render ()
sketch (Circle (Vec2 Double
x Double
y) Double
r) = Double -> Double -> Double -> Double -> Double -> Render ()
arc Double
x Double
y Double
r Double
0 (Double
2Double -> Double -> Double
forall a. Num a => a -> a -> a
*Double
forall a. Floating a => a
pi)
instance Sketch Ellipse where
sketch :: Ellipse -> Render ()
sketch (Ellipse Transformation
t) = Render () -> Render ()
forall a. Render a -> Render a
cairoScope (Render () -> Render ()) -> Render () -> Render ()
forall a b. (a -> b) -> a -> b
$ do
Matrix -> Render ()
C.transform (Transformation -> Matrix
toCairoMatrix Transformation
t)
Circle -> Render ()
forall a. Sketch a => a -> Render ()
sketch (Vec2 -> Double -> Circle
Circle Vec2
forall v. VectorSpace v => v
zero Double
1)
data Cross = Cross
{ Cross -> Vec2
_crossCenter :: !Vec2
, Cross -> Double
_crossRadius :: !Double
} deriving (Cross -> Cross -> Bool
(Cross -> Cross -> Bool) -> (Cross -> Cross -> Bool) -> Eq Cross
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Cross -> Cross -> Bool
== :: Cross -> Cross -> Bool
$c/= :: Cross -> Cross -> Bool
/= :: Cross -> Cross -> Bool
Eq, Eq Cross
Eq Cross
-> (Cross -> Cross -> Ordering)
-> (Cross -> Cross -> Bool)
-> (Cross -> Cross -> Bool)
-> (Cross -> Cross -> Bool)
-> (Cross -> Cross -> Bool)
-> (Cross -> Cross -> Cross)
-> (Cross -> Cross -> Cross)
-> Ord Cross
Cross -> Cross -> Bool
Cross -> Cross -> Ordering
Cross -> Cross -> Cross
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: Cross -> Cross -> Ordering
compare :: Cross -> Cross -> Ordering
$c< :: Cross -> Cross -> Bool
< :: Cross -> Cross -> Bool
$c<= :: Cross -> Cross -> Bool
<= :: Cross -> Cross -> Bool
$c> :: Cross -> Cross -> Bool
> :: Cross -> Cross -> Bool
$c>= :: Cross -> Cross -> Bool
>= :: Cross -> Cross -> Bool
$cmax :: Cross -> Cross -> Cross
max :: Cross -> Cross -> Cross
$cmin :: Cross -> Cross -> Cross
min :: Cross -> Cross -> Cross
Ord, Int -> Cross -> String -> String
[Cross] -> String -> String
Cross -> String
(Int -> Cross -> String -> String)
-> (Cross -> String) -> ([Cross] -> String -> String) -> Show Cross
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
$cshowsPrec :: Int -> Cross -> String -> String
showsPrec :: Int -> Cross -> String -> String
$cshow :: Cross -> String
show :: Cross -> String
$cshowList :: [Cross] -> String -> String
showList :: [Cross] -> String -> String
Show)
instance Sketch Cross where
sketch :: Cross -> Render ()
sketch (Cross Vec2
center Double
r) = do
let lowerRight :: Vec2
lowerRight = Transformation -> Vec2 -> Vec2
forall geo. Transform geo => Transformation -> geo -> geo
G.transform (Vec2 -> Angle -> Transformation
rotateAround Vec2
center (Double -> Angle
deg Double
45)) (Vec2
center Vec2 -> Vec2 -> Vec2
forall v. VectorSpace v => v -> v -> v
+. Double -> Double -> Vec2
Vec2 Double
r Double
0)
line1 :: Line
line1 = Vec2 -> Angle -> Double -> Line
angledLine Vec2
lowerRight (Double -> Angle
deg (Double
45Double -> Double -> Double
forall a. Num a => a -> a -> a
+Double
180)) (Double
2Double -> Double -> Double
forall a. Num a => a -> a -> a
*Double
r)
line2 :: Line
line2 = Transformation -> Line -> Line
forall geo. Transform geo => Transformation -> geo -> geo
G.transform (Vec2 -> Angle -> Transformation
rotateAround Vec2
center (Double -> Angle
deg Double
90)) Line
line1
Line -> Render ()
forall a. Sketch a => a -> Render ()
sketch Line
line1
Line -> Render ()
forall a. Sketch a => a -> Render ()
sketch Line
line2
instance Sketch Transformation where
sketch :: Transformation -> Render ()
sketch Transformation
t = do
let grid :: [Line]
grid = [Vec2 -> Vec2 -> Line
Line (Double -> Double -> Vec2
Vec2 Double
0 Double
y) (Double -> Double -> Vec2
Vec2 Double
100 Double
y) | Double
y <- (Integer -> Double) -> [Integer] -> [Double]
forall a b. (a -> b) -> [a] -> [b]
map Integer -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral [Integer
0,Integer
20..Integer
100]]
[Line] -> [Line] -> [Line]
forall a. [a] -> [a] -> [a]
++ [Vec2 -> Vec2 -> Line
Line (Double -> Double -> Vec2
Vec2 Double
x Double
0) (Double -> Double -> Vec2
Vec2 Double
x Double
100) | Double
x <- (Integer -> Double) -> [Integer] -> [Double]
forall a b. (a -> b) -> [a] -> [b]
map Integer -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral [Integer
0,Integer
20..Integer
100]]
[Line] -> Render ()
forall a. Sketch a => a -> Render ()
sketch (Transformation -> [Line] -> [Line]
forall geo. Transform geo => Transformation -> geo -> geo
G.transform Transformation
t [Line]
grid)
arcSketch
:: Vec2
-> Double
-> Angle
-> Angle
-> Render ()
arcSketch :: Vec2 -> Double -> Angle -> Angle -> Render ()
arcSketch (Vec2 Double
x Double
y) Double
r Angle
angleStart Angle
angleEnd
= Double -> Double -> Double -> Double -> Double -> Render ()
arc Double
x Double
y Double
r (Angle -> Double
getRad Angle
angleStart) (Angle -> Double
getRad Angle
angleEnd)
arcSketchNegative
:: Vec2
-> Double
-> Angle
-> Angle
-> Render ()
arcSketchNegative :: Vec2 -> Double -> Angle -> Angle -> Render ()
arcSketchNegative (Vec2 Double
x Double
y) Double
r Angle
angleStart Angle
angleEnd
= Double -> Double -> Double -> Double -> Double -> Render ()
arcNegative Double
x Double
y Double
r (Angle -> Double
getRad Angle
angleStart) (Angle -> Double
getRad Angle
angleEnd)
instance Sketch BoundingBox where
sketch :: BoundingBox -> Render ()
sketch (BoundingBox (Vec2 Double
xlo Double
ylo) (Vec2 Double
xhi Double
yhi)) = do
let w :: Double
w = Double
xhi Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
xlo
h :: Double
h = Double
yhi Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
ylo
Double -> Double -> Double -> Double -> Render ()
rectangle Double
xlo Double
ylo Double
w Double
h
Double -> Double -> Render ()
moveTo Double
xlo Double
ylo
Double -> Double -> Render ()
lineTo Double
xhi Double
yhi
Double -> Double -> Render ()
moveTo Double
xhi Double
ylo
Double -> Double -> Render ()
lineTo Double
xlo Double
yhi
data CartesianParams = CartesianParams
{ CartesianParams -> Int
_cartesianMinX :: !Int
, CartesianParams -> Int
_cartesianMaxX :: !Int
, CartesianParams -> Int
_cartesianMinY :: !Int
, CartesianParams -> Int
_cartesianMaxY :: !Int
, CartesianParams -> Double
_cartesianAlpha :: !Double
, CartesianParams -> Bool
_renderAxisLabels :: !Bool
, CartesianParams -> Bool
_renderTens :: !Bool
, CartesianParams -> Bool
_renderHundreds :: !Bool
} deriving (CartesianParams -> CartesianParams -> Bool
(CartesianParams -> CartesianParams -> Bool)
-> (CartesianParams -> CartesianParams -> Bool)
-> Eq CartesianParams
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: CartesianParams -> CartesianParams -> Bool
== :: CartesianParams -> CartesianParams -> Bool
$c/= :: CartesianParams -> CartesianParams -> Bool
/= :: CartesianParams -> CartesianParams -> Bool
Eq, Eq CartesianParams
Eq CartesianParams
-> (CartesianParams -> CartesianParams -> Ordering)
-> (CartesianParams -> CartesianParams -> Bool)
-> (CartesianParams -> CartesianParams -> Bool)
-> (CartesianParams -> CartesianParams -> Bool)
-> (CartesianParams -> CartesianParams -> Bool)
-> (CartesianParams -> CartesianParams -> CartesianParams)
-> (CartesianParams -> CartesianParams -> CartesianParams)
-> Ord CartesianParams
CartesianParams -> CartesianParams -> Bool
CartesianParams -> CartesianParams -> Ordering
CartesianParams -> CartesianParams -> CartesianParams
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: CartesianParams -> CartesianParams -> Ordering
compare :: CartesianParams -> CartesianParams -> Ordering
$c< :: CartesianParams -> CartesianParams -> Bool
< :: CartesianParams -> CartesianParams -> Bool
$c<= :: CartesianParams -> CartesianParams -> Bool
<= :: CartesianParams -> CartesianParams -> Bool
$c> :: CartesianParams -> CartesianParams -> Bool
> :: CartesianParams -> CartesianParams -> Bool
$c>= :: CartesianParams -> CartesianParams -> Bool
>= :: CartesianParams -> CartesianParams -> Bool
$cmax :: CartesianParams -> CartesianParams -> CartesianParams
max :: CartesianParams -> CartesianParams -> CartesianParams
$cmin :: CartesianParams -> CartesianParams -> CartesianParams
min :: CartesianParams -> CartesianParams -> CartesianParams
Ord, Int -> CartesianParams -> String -> String
[CartesianParams] -> String -> String
CartesianParams -> String
(Int -> CartesianParams -> String -> String)
-> (CartesianParams -> String)
-> ([CartesianParams] -> String -> String)
-> Show CartesianParams
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
$cshowsPrec :: Int -> CartesianParams -> String -> String
showsPrec :: Int -> CartesianParams -> String -> String
$cshow :: CartesianParams -> String
show :: CartesianParams -> String
$cshowList :: [CartesianParams] -> String -> String
showList :: [CartesianParams] -> String -> String
Show)
instance Default CartesianParams where
def :: CartesianParams
def = CartesianParams
{ _cartesianMinX :: Int
_cartesianMinX = -Int
1000
, _cartesianMaxX :: Int
_cartesianMaxX = Int
1000
, _cartesianMinY :: Int
_cartesianMinY = -Int
1000
, _cartesianMaxY :: Int
_cartesianMaxY = Int
1000
, _cartesianAlpha :: Double
_cartesianAlpha = Double
1
, _renderAxisLabels :: Bool
_renderAxisLabels = Bool
True
, _renderTens :: Bool
_renderTens = Bool
True
, _renderHundreds :: Bool
_renderHundreds = Bool
True
}
cartesianCoordinateSystem :: CartesianParams -> Render ()
cartesianCoordinateSystem :: CartesianParams -> Render ()
cartesianCoordinateSystem params :: CartesianParams
params@CartesianParams{Bool
Double
Int
_cartesianMinX :: CartesianParams -> Int
_cartesianMaxX :: CartesianParams -> Int
_cartesianMinY :: CartesianParams -> Int
_cartesianMaxY :: CartesianParams -> Int
_cartesianAlpha :: CartesianParams -> Double
_renderAxisLabels :: CartesianParams -> Bool
_renderTens :: CartesianParams -> Bool
_renderHundreds :: CartesianParams -> Bool
_cartesianMinX :: Int
_cartesianMaxX :: Int
_cartesianMinY :: Int
_cartesianMaxY :: Int
_cartesianAlpha :: Double
_renderAxisLabels :: Bool
_renderTens :: Bool
_renderHundreds :: Bool
..} = Render () -> Render () -> Render ()
forall after a. Render after -> Render a -> Render a
grouped (Double -> Render ()
paintWithAlpha Double
_cartesianAlpha) (Render () -> Render ()) -> Render () -> Render ()
forall a b. (a -> b) -> a -> b
$ do
let vec2 :: a -> a -> Vec2
vec2 a
x a
y = Double -> Double -> Vec2
Vec2 (a -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral a
x) (a -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral a
y)
Double -> Render ()
setLineWidth Double
1
let CartesianParams{_cartesianMinX :: CartesianParams -> Int
_cartesianMinX=Int
minX, _cartesianMaxX :: CartesianParams -> Int
_cartesianMaxX=Int
maxX, _cartesianMinY :: CartesianParams -> Int
_cartesianMinY=Int
minY, _cartesianMaxY :: CartesianParams -> Int
_cartesianMaxY=Int
maxY} = CartesianParams
params
Bool -> Render () -> Render ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
_renderHundreds (Render () -> Render ()) -> Render () -> Render ()
forall a b. (a -> b) -> a -> b
$ Render () -> Render ()
forall a. Render a -> Render a
cairoScope (Render () -> Render ()) -> Render () -> Render ()
forall a b. (a -> b) -> a -> b
$ do
AlphaColor Double -> Render ()
forall color. CairoColor color => color -> Render ()
setColor (Double -> Double -> Double -> Double -> AlphaColor Double
hsva Double
0 Double
0 Double
0 Double
0.5)
[Render ()] -> Render ()
forall (t :: * -> *) (m :: * -> *) a.
(Foldable t, Monad m) =>
t (m a) -> m ()
sequence_ [ Line -> Render ()
forall a. Sketch a => a -> Render ()
sketch (Vec2 -> Vec2 -> Line
Line (Int -> Int -> Vec2
forall {a} {a}. (Integral a, Integral a) => a -> a -> Vec2
vec2 Int
x Int
minY) (Int -> Int -> Vec2
forall {a} {a}. (Integral a, Integral a) => a -> a -> Vec2
vec2 Int
x Int
maxY))
| Int
x <- [Int
minX, Int
minXInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
100 .. Int
maxX] ]
[Render ()] -> Render ()
forall (t :: * -> *) (m :: * -> *) a.
(Foldable t, Monad m) =>
t (m a) -> m ()
sequence_ [ Line -> Render ()
forall a. Sketch a => a -> Render ()
sketch (Vec2 -> Vec2 -> Line
Line (Int -> Int -> Vec2
forall {a} {a}. (Integral a, Integral a) => a -> a -> Vec2
vec2 Int
minX Int
y) (Int -> Int -> Vec2
forall {a} {a}. (Integral a, Integral a) => a -> a -> Vec2
vec2 Int
maxX Int
y))
| Int
y <- [Int
minY, Int
minYInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
100 .. Int
maxY] ]
Render ()
stroke
Bool -> Render () -> Render ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
_renderTens (Render () -> Render ()) -> Render () -> Render ()
forall a b. (a -> b) -> a -> b
$ Render () -> Render ()
forall a. Render a -> Render a
cairoScope (Render () -> Render ()) -> Render () -> Render ()
forall a b. (a -> b) -> a -> b
$ do
AlphaColor Double -> Render ()
forall color. CairoColor color => color -> Render ()
setColor (Double -> Double -> Double -> Double -> AlphaColor Double
hsva Double
0 Double
0 Double
0 Double
0.2)
[Double] -> Double -> Render ()
setDash [Double
4,Double
6] Double
2
let skipHundreds :: a -> Bool
skipHundreds a
i = Bool -> Bool
not Bool
_renderHundreds Bool -> Bool -> Bool
|| a -> a -> a
forall a. Integral a => a -> a -> a
mod a
i a
100 a -> a -> Bool
forall a. Eq a => a -> a -> Bool
/= a
0
[Render ()] -> Render ()
forall (t :: * -> *) (m :: * -> *) a.
(Foldable t, Monad m) =>
t (m a) -> m ()
sequence_ [ Line -> Render ()
forall a. Sketch a => a -> Render ()
sketch (Vec2 -> Vec2 -> Line
Line (Int -> Int -> Vec2
forall {a} {a}. (Integral a, Integral a) => a -> a -> Vec2
vec2 Int
x Int
minY) (Int -> Int -> Vec2
forall {a} {a}. (Integral a, Integral a) => a -> a -> Vec2
vec2 Int
x Int
maxY))
| Int
x <- [Int
minX, Int
minXInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
10 .. Int
maxX]
, Int -> Bool
forall {a}. Integral a => a -> Bool
skipHundreds Int
x ]
[Render ()] -> Render ()
forall (t :: * -> *) (m :: * -> *) a.
(Foldable t, Monad m) =>
t (m a) -> m ()
sequence_ [ Line -> Render ()
forall a. Sketch a => a -> Render ()
sketch (Vec2 -> Vec2 -> Line
Line (Int -> Int -> Vec2
forall {a} {a}. (Integral a, Integral a) => a -> a -> Vec2
vec2 Int
minX Int
y) (Int -> Int -> Vec2
forall {a} {a}. (Integral a, Integral a) => a -> a -> Vec2
vec2 Int
maxX Int
y))
| Int
y <- [Int
minY, Int
minYInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
10 .. Int
maxY]
, Int -> Bool
forall {a}. Integral a => a -> Bool
skipHundreds Int
y]
Render ()
stroke
Bool -> Render () -> Render ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
_renderAxisLabels (Render () -> Render ()) -> Render () -> Render ()
forall a b. (a -> b) -> a -> b
$ Render () -> Render ()
forall a. Render a -> Render a
cairoScope (Render () -> Render ()) -> Render () -> Render ()
forall a b. (a -> b) -> a -> b
$ do
let centeredText :: Int -> Int -> String -> Render ()
centeredText :: Int -> Int -> String -> Render ()
centeredText Int
x Int
y String
str = do
Double -> Double -> Render ()
moveTo (Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
x) (Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
y)
HAlign -> VAlign -> String -> Render ()
forall string.
CairoString string =>
HAlign -> VAlign -> string -> Render ()
showTextAligned HAlign
HCenter VAlign
VTop String
str
Double -> Render ()
setFontSize Double
8
Color Double -> Render ()
forall color. CairoColor color => color -> Render ()
setColor (Int -> Color Double
mma Int
0)
[Render ()] -> Render ()
forall (t :: * -> *) (m :: * -> *) a.
(Foldable t, Monad m) =>
t (m a) -> m ()
sequence_ [ Int -> Int -> String -> Render ()
centeredText Int
x Int
y (Int -> String
forall a. Show a => a -> String
show Int
x String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"," String -> String -> String
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
y)
| Int
x <- [Int
minX, Int
minXInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
100 .. Int
maxX]
, Int
y <- [Int
minY, Int
minYInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
100 .. Int
maxY] ]
data PolarParams = PolarParams
{ PolarParams -> Vec2
_polarCenter :: !Vec2
, PolarParams -> Double
_polarMaxRadius :: !Double
, PolarParams -> Double
_polarAlpha :: !Double
} deriving (PolarParams -> PolarParams -> Bool
(PolarParams -> PolarParams -> Bool)
-> (PolarParams -> PolarParams -> Bool) -> Eq PolarParams
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: PolarParams -> PolarParams -> Bool
== :: PolarParams -> PolarParams -> Bool
$c/= :: PolarParams -> PolarParams -> Bool
/= :: PolarParams -> PolarParams -> Bool
Eq, Eq PolarParams
Eq PolarParams
-> (PolarParams -> PolarParams -> Ordering)
-> (PolarParams -> PolarParams -> Bool)
-> (PolarParams -> PolarParams -> Bool)
-> (PolarParams -> PolarParams -> Bool)
-> (PolarParams -> PolarParams -> Bool)
-> (PolarParams -> PolarParams -> PolarParams)
-> (PolarParams -> PolarParams -> PolarParams)
-> Ord PolarParams
PolarParams -> PolarParams -> Bool
PolarParams -> PolarParams -> Ordering
PolarParams -> PolarParams -> PolarParams
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: PolarParams -> PolarParams -> Ordering
compare :: PolarParams -> PolarParams -> Ordering
$c< :: PolarParams -> PolarParams -> Bool
< :: PolarParams -> PolarParams -> Bool
$c<= :: PolarParams -> PolarParams -> Bool
<= :: PolarParams -> PolarParams -> Bool
$c> :: PolarParams -> PolarParams -> Bool
> :: PolarParams -> PolarParams -> Bool
$c>= :: PolarParams -> PolarParams -> Bool
>= :: PolarParams -> PolarParams -> Bool
$cmax :: PolarParams -> PolarParams -> PolarParams
max :: PolarParams -> PolarParams -> PolarParams
$cmin :: PolarParams -> PolarParams -> PolarParams
min :: PolarParams -> PolarParams -> PolarParams
Ord, Int -> PolarParams -> String -> String
[PolarParams] -> String -> String
PolarParams -> String
(Int -> PolarParams -> String -> String)
-> (PolarParams -> String)
-> ([PolarParams] -> String -> String)
-> Show PolarParams
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
$cshowsPrec :: Int -> PolarParams -> String -> String
showsPrec :: Int -> PolarParams -> String -> String
$cshow :: PolarParams -> String
show :: PolarParams -> String
$cshowList :: [PolarParams] -> String -> String
showList :: [PolarParams] -> String -> String
Show)
instance Default PolarParams where
def :: PolarParams
def = PolarParams
{ _polarCenter :: Vec2
_polarCenter = Vec2
forall v. VectorSpace v => v
zero
, _polarMaxRadius :: Double
_polarMaxRadius = Double
1000
, _polarAlpha :: Double
_polarAlpha = Double
1
}
radialCoordinateSystem :: PolarParams -> Render ()
radialCoordinateSystem :: PolarParams -> Render ()
radialCoordinateSystem PolarParams{_polarCenter :: PolarParams -> Vec2
_polarCenter=Vec2
center, _polarMaxRadius :: PolarParams -> Double
_polarMaxRadius=Double
maxR} = Render () -> Render ()
forall a. Render a -> Render a
cairoScope (Render () -> Render ()) -> Render () -> Render ()
forall a b. (a -> b) -> a -> b
$ do
Double -> Render ()
setLineWidth Double
1
Color Double -> Render ()
forall color. CairoColor color => color -> Render ()
setColor (Double -> Double -> Double -> Color Double
hsv Double
0 Double
0 Double
0)
[Render ()] -> Render ()
forall (t :: * -> *) (m :: * -> *) a.
(Foldable t, Monad m) =>
t (m a) -> m ()
sequence_ [ Circle -> Render ()
forall a. Sketch a => a -> Render ()
sketch (Vec2 -> Double -> Circle
Circle Vec2
center (Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
r)) Render () -> Render () -> Render ()
forall after a. Render after -> Render a -> Render a
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Render ()
stroke
| Int
r <- [Int
100, Int
200 .. Double -> Int
forall b. Integral b => Double -> b
forall a b. (RealFrac a, Integral b) => a -> b
ceiling Double
maxR :: Int] ]
[Render ()] -> Render ()
forall (t :: * -> *) (m :: * -> *) a.
(Foldable t, Monad m) =>
t (m a) -> m ()
sequence_ [ Line -> Render ()
forall a. Sketch a => a -> Render ()
sketch (Vec2 -> Angle -> Double -> Line
angledLine Vec2
center (Double -> Angle
deg (Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
angle)) Double
maxR) Render () -> Render () -> Render ()
forall after a. Render after -> Render a -> Render a
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Render ()
stroke
| Int
angle <- [Int] -> [Int]
forall a. HasCallStack => [a] -> [a]
init [Int
0, Int
45 .. Int
360 :: Int] ]
AlphaColor Double -> Render ()
forall color. CairoColor color => color -> Render ()
setColor (Double -> Double -> Double -> Double -> AlphaColor Double
hsva Double
0 Double
0 Double
0 Double
0.5)
[Render ()] -> Render ()
forall (t :: * -> *) (m :: * -> *) a.
(Foldable t, Monad m) =>
t (m a) -> m ()
sequence_ [ Circle -> Render ()
forall a. Sketch a => a -> Render ()
sketch (Vec2 -> Double -> Circle
Circle Vec2
center (Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
r)) Render () -> Render () -> Render ()
forall after a. Render after -> Render a -> Render a
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Render ()
stroke
| Int
r <- [Int
25, Int
50 .. Double -> Int
forall b. Integral b => Double -> b
forall a b. (RealFrac a, Integral b) => a -> b
ceiling Double
maxR :: Int]
, Int -> Int -> Int
forall a. Integral a => a -> a -> a
mod Int
r Int
100 Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
0 ]
[Render ()] -> Render ()
forall (t :: * -> *) (m :: * -> *) a.
(Foldable t, Monad m) =>
t (m a) -> m ()
sequence_ [ Line -> Render ()
forall a. Sketch a => a -> Render ()
sketch (Vec2 -> Angle -> Double -> Line
angledLine Vec2
center (Double -> Angle
deg (Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
angle)) Double
maxR) Render () -> Render () -> Render ()
forall after a. Render after -> Render a -> Render a
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Render ()
stroke
| Int
angle <- [Int] -> [Int]
forall a. HasCallStack => [a] -> [a]
init [Int
0, Int
15 .. Int
360 :: Int]
, Int -> Int -> Int
forall a. Integral a => a -> a -> a
mod Int
angle Int
45 Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
0 ]
withOperator :: Operator -> Render a -> Render a
withOperator :: forall a. Operator -> Render a -> Render a
withOperator Operator
op Render a
actions = do
Operator
formerOp <- Render Operator
getOperator
Operator -> Render ()
setOperator Operator
op
a
result <- Render a
actions
Operator -> Render ()
setOperator Operator
formerOp
a -> Render a
forall a. a -> Render a
forall (f :: * -> *) a. Applicative f => a -> f a
pure a
result
cairoScope :: Render a -> Render a
cairoScope :: forall a. Render a -> Render a
cairoScope Render a
actions = Render ()
save Render () -> Render a -> Render a
forall after a. Render after -> Render a -> Render a
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Render a
actions Render a -> Render () -> Render a
forall a b. Render a -> Render b -> Render a
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Render ()
restore
grouped :: Render after -> Render a -> Render a
grouped :: forall after a. Render after -> Render a -> Render a
grouped Render after
afterwards Render a
actions = Render a -> Render a
forall a. Render a -> Render a
cairoScope (Render a -> Render a) -> Render a -> Render a
forall a b. (a -> b) -> a -> b
$ Render ()
pushGroup Render () -> Render a -> Render a
forall after a. Render after -> Render a -> Render a
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Render a
actions Render a -> Render () -> Render a
forall a b. Render a -> Render b -> Render a
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Render ()
popGroupToSource Render a -> Render after -> Render a
forall a b. Render a -> Render b -> Render a
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Render after
afterwards
fromCairoMatrix :: Matrix -> Transformation
fromCairoMatrix :: Matrix -> Transformation
fromCairoMatrix (Matrix Double
ca Double
cb Double
cc Double
cd Double
ce Double
cf) =
let a :: Double
a = Double
ca
b :: Double
b = Double
cc
c :: Double
c = Double
ce
d :: Double
d = Double
cb
e :: Double
e = Double
cd
f :: Double
f = Double
cf
in Mat2 -> Vec2 -> Transformation
Transformation (Double -> Double -> Double -> Double -> Mat2
Mat2 Double
a Double
b Double
d Double
e) (Double -> Double -> Vec2
Vec2 Double
c Double
f)
toCairoMatrix :: Transformation -> C.Matrix
toCairoMatrix :: Transformation -> Matrix
toCairoMatrix Transformation
trafo =
let Transformation (Mat2 Double
a Double
b Double
d Double
e) (Vec2 Double
c Double
f) = Transformation
trafo
ca :: Double
ca = Double
a
cc :: Double
cc = Double
b
ce :: Double
ce = Double
c
cb :: Double
cb = Double
d
cd :: Double
cd = Double
e
cf :: Double
cf = Double
f
in Double -> Double -> Double -> Double -> Double -> Double -> Matrix
Matrix Double
ca Double
cb Double
cc Double
cd Double
ce Double
cf