module Graphics.UI.GLUT.Turtle.TriangleTools (
Pos,
far,
index3,
deleteIndex,
distant3,
within,
isRight,
online,
deleteOnline,
draw,
pa, pb, pc, pd, pe
) where
import Graphics.UI.GLUT
import System.Environment
far :: [Pos] -> Int
far = maximumIndex . map distance2
deleteOnline :: [Pos] -> [Pos]
deleteOnline xs = init $ tail $ dol $ last xs : xs ++ [head xs]
dol :: [Pos] -> [Pos]
dol [a, b] = [a, b]
dol (a : ps@(b : ps'@(c : _)))
| online (a, b, c) = a : dol ps'
| otherwise = a : dol ps
dol ps = ps
maximumIndex :: Ord a => [a] -> Int
maximumIndex = fst . maximumIndexGen
index3 :: [a] -> Int -> (a, a, a)
index3 xs i = (xs' !! i, xs' !! (i + 1), xs' !! (i + 2))
where
xs' = last xs : xs ++ [head xs]
deleteIndex :: [a] -> Int -> [a]
deleteIndex xs i = take i xs ++ drop (i + 1) xs
maximumIndexGen :: Ord a => [a] -> (Int, a)
maximumIndexGen [x] = (0, x)
maximumIndexGen (x : xs)
| x >= x' = (0, x)
| otherwise = (i + 1, x')
where
(i, x') = maximumIndexGen xs
maximumIndexGen _ = error "maximumIndexGen: not implemented"
draw :: [Pos] -> [(Pos, Pos, Pos)] -> IO ()
draw pl trs = do
prgName <- getProgName
rawArgs <- getArgs
_args <- initialize prgName rawArgs
_ <- createWindow "GLTest"
displayCallback $= do
color (Color4 1 1 1 0 :: Color4 GLfloat)
drawTriangles trs
color (Color4 1 0 0 0 :: Color4 GLfloat)
drawPolyline pl
swapBuffers
flush
mainLoop
drawTriangles :: [(Pos, Pos, Pos)] -> IO ()
drawTriangles ps = preservingMatrix $
renderPrimitive Triangles $ mapM_ vertex $ trianglesToVertex2 ps
trianglesToVertex2 :: [(Pos, Pos, Pos)] -> [Vertex2 GLfloat]
trianglesToVertex2 [] = []
trianglesToVertex2 ((a, b, c) : rest) =
toVertex2 a : toVertex2 b : toVertex2 c : trianglesToVertex2 rest
toVertex2 :: (Double, Double) -> Vertex2 GLfloat
toVertex2 (x, y) = Vertex2
(fromRational $ toRational x / 20) (fromRational $ toRational y / 20)
drawPolyline :: [Pos] -> IO ()
drawPolyline ps = preservingMatrix $
renderPrimitive LineLoop $ mapM_ (vertex . toVertex2) ps
type Pos = (Double, Double)
isRight :: (Pos, Pos, Pos) -> Bool
isRight ((xa, ya), (xb, yb), (xc, yc))
| 0 < xd * ye xe * yd = True
| 0 == xd * ye xe * yd = error "isRight: bad triangle"
| otherwise = False
where
(xd, yd) = (xa xb, ya yb)
(xe, ye) = (xc xb, yc yb)
distance2 :: Floating a => (a, a) -> a
distance2 (x, y) = x ** 2 + y ** 2
maximumby32 :: Ord b => (a -> b) -> [a] -> ((a, a, a), [a])
maximumby32 b xs = maximumby3Gen2 b $ last xs : xs ++ [head xs]
maximumby3Gen2 :: Ord b => (a -> b) -> [a] -> ((a, a, a), [a])
maximumby3Gen2 _ [x, y, z] = ((x, y, z), [x, z])
maximumby3Gen2 b (x : ys@(y : (zs@(z : _))))
| b y > b y' = ((x, y, z), x : zs)
| otherwise = (t, x : ps)
where
(t@(_, y', _), ps) = maximumby3Gen2 b ys
maximumby3Gen2 _ _ = error "maximumby3Gen2: not implemented"
distant3 :: [Pos] -> ((Pos, Pos, Pos), [Pos])
distant3 ps = let (t, ps') = maximumby32 distance2 ps in (t, init $ tail ps')
within :: (Pos, Pos, Pos) -> Pos -> Bool
within (a, b, c) d
| online (d, a, b) || online (d, b, c) || online (d, c, a) = False
| otherwise = isRight (a, b, c) &&
isRight (d, a, b) && isRight (d, b, c) && isRight (d, c, a)
online :: (Pos, Pos, Pos) -> Bool
online ((xa, ya), (xb, yb), (xc, yc)) = 0 == xd * ye xe * yd
where
(xd, yd) = (xa xb, ya yb)
(xe, ye) = (xc xb, yc yb)
pa, pb, pc, pd, pe :: Pos
pa = (0, 4)
pb = (4, 4)
pc = (4, 0)
pd = (3, 3)
pe = (2, 2)