0% acharam este documento útil (0 voto)
4 visualizações4 páginas

Projeto Hs

Enviado por

gambomfim
Direitos autorais
© © All Rights Reserved
Levamos muito a sério os direitos de conteúdo. Se você suspeita que este conteúdo é seu, reivindique-o aqui.
Formatos disponíveis
Baixe no formato TXT, PDF, TXT ou leia on-line no Scribd
0% acharam este documento útil (0 voto)
4 visualizações4 páginas

Projeto Hs

Enviado por

gambomfim
Direitos autorais
© © All Rights Reserved
Levamos muito a sério os direitos de conteúdo. Se você suspeita que este conteúdo é seu, reivindique-o aqui.
Formatos disponíveis
Baixe no formato TXT, PDF, TXT ou leia on-line no Scribd
Você está na página 1/ 4

{-# LANGUAGE OverloadedStrings #-}

import CodeWorld
import qualified Data.Text

main = activityOf ([], NaoIniciado, Cir, (11,11)) atualiza visualiza

type World = ( [Figura],


Estado,
Modo,
Point ) -- posição do cursor

data Modo = Ret | Cir | Dl | Movendo Figura

data Estado = NaoIniciado |


DesenhandoRC Point Point |
DesenhandoLivre [Point] |
MovendoFigura Figura

data Figura = Circulo Point Double |


Retangulo Point Point |
Linha [Point]
deriving (Eq)

---------------- VISUALIZAÇÃO DO MUNDO


visualiza :: World -> Picture

visualiza (cs, NaoIniciado, m, pc) =


cursor m pc & figsToPicture cs

visualiza (cs, DesenhandoRC p@(x,y) q, Cir, pc) =


cursor Cir pc &
colored red circuloProvisorio &
figsToPicture cs
where
circuloProvisorio =
translated x y
(circle (vectorLength (vectorDifference p q)))

visualiza (cs, DesenhandoRC p q , Ret, pc) =


cursor Ret pc &
colored red retanguloProvisorio &
figsToPicture cs
where
retanguloProvisorio =
translated x y
(rectangle (fst pq) (snd pq))
pq = vectorDifference q p
(x, y) = vectorSum p (scaledVector 0.5 pq)

-- Visualização do desenho livre


visualiza (cs, DesenhandoLivre pontos, Dl, pc) =
cursor Dl pc &
colored red (polyline pontos) &
figsToPicture cs

-- Visualização durante o movimento da figura


visualiza (cs, MovendoFigura fig, Movendo figAtual, pc) =
cursor (Movendo figAtual) pc &
colored green (figToPicture figAtual) &
figsToPicture (filter (/= fig) cs)

cursor :: Modo -> Point -> Picture


cursor m (x, y)=
colored green
(translated x y (crs m))
where
crs Ret = solidRectangle 0.4 0.4
crs Cir = solidCircle 0.2
crs Dl = solidCircle 0.1 -- Representação do cursor no modo de desenho livre
crs (Movendo _) = solidCircle 0.3 -- Cursor para o modo de mover

figsToPicture :: [Figura] -> Picture


figsToPicture [] = blank
figsToPicture (f : fs) = figToPicture f & figsToPicture fs

figToPicture :: Figura -> Picture


figToPicture (Circulo c r) =
translated (fst c) (snd c) (circle r)
figToPicture (Retangulo p q) =
translated x y (rectangle (fst pq) (snd pq))
where
pq = vectorDifference q p
(x, y) = vectorSum p (scaledVector 0.5 pq)
-- Desenha a linha (desenho livre)
figToPicture (Linha pontos) = polyline pontos

--------------- ATUALIZAÇÃO DO MUNDO


atualiza :: Event -> World -> World

-- DESENHO DE RETÂNGULOS
atualiza (KeyPress "R") (cs, st, _, pc) = (cs, st, Ret, pc)

atualiza (PointerPress p) (cs, _, Ret, _) = (cs, DesenhandoRC p p, Ret, p)

atualiza (PointerMovement q) (cs, DesenhandoRC p _, Ret, _) =


(cs, DesenhandoRC p q, Ret, q)

atualiza (PointerRelease q) (cs, DesenhandoRC p _, Ret, _) =


(Retangulo p q: cs, NaoIniciado, Ret, q)

-- DESENHO DE CÍRCULOS
atualiza (KeyPress "C") (cs, st, _, pc) = (cs, st, Cir, pc)

atualiza (PointerPress p) (cs, _, Cir, _) = (cs, DesenhandoRC p p, Cir, p)

atualiza (PointerMovement q) (cs, DesenhandoRC p _, Cir, _) =


(cs, DesenhandoRC p q, Cir, q)

atualiza (PointerRelease q) (cs, DesenhandoRC p _, Cir, _) =


(Circulo p (vectorLength (vectorDifference p q)) : cs, NaoIniciado, Cir, q)

-- DESENHO LIVRE
atualiza (KeyPress "D") (cs, st, _, pc) = (cs, st, Dl, pc)

atualiza (PointerPress p) (cs, _, Dl, _) = (cs, DesenhandoLivre [p], Dl, p)

atualiza (PointerMovement q) (cs, DesenhandoLivre pontos, Dl, _) =


(cs, DesenhandoLivre (pontos ++ [q]), Dl, q)
atualiza (PointerRelease _) (cs, DesenhandoLivre pontos, Dl, q) =
(Linha pontos : cs, NaoIniciado, Dl, q)

-- MOVIMENTO DE FIGURAS
atualiza (KeyPress "M") (cs, _, _, pc) =
case encontraFigura pc cs of
Just figura -> (cs, MovendoFigura figura, Movendo figura, pc)
Nothing -> (cs, NaoIniciado, Cir, pc)

-- Movimenta a figura com o cursor


atualiza (PointerMovement q) (cs, MovendoFigura figura, Movendo _, _) =
let novaFigura = moveFiguraPara figura q
in (replaceFigura figura novaFigura cs, MovendoFigura novaFigura, Movendo
novaFigura, q)

-- Solta a figura ao liberar o botão do mouse


atualiza (PointerRelease _) (cs, MovendoFigura _, Movendo _, q) =
(cs, NaoIniciado, Cir, q)

-- NENHUMA OPERAÇÃO INICIADA


atualiza (PointerMovement q) (cs, NaoIniciado, st, _) =
(cs, NaoIniciado, st, q)

-- OUTROS
atualiza _ w = w

-- FUNÇÕES AUXILIARES

-- Função que verifica se o ponto está dentro de uma figura


encontraFigura :: Point -> [Figura] -> Maybe Figura
encontraFigura p = foldr (\f acc -> if pontoDentroFigura p f then Just f else acc)
Nothing

-- Função que move uma figura para uma nova posição


moveFiguraPara :: Figura -> Point -> Figura
moveFiguraPara (Circulo (cx, cy) r) (nx, ny) =
Circulo (nx, ny) r

moveFiguraPara (Retangulo (x1, y1) (x2, y2)) (nx, ny) =


let deslocamento = (nx - x1, ny - y1)
in Retangulo (nx, ny) (x2 + fst deslocamento, y2 + snd deslocamento)

moveFiguraPara (Linha pontos) novoCentro =


let deslocamento = (fst novoCentro - fst (head pontos), snd novoCentro - snd
(head pontos))
in Linha (map (\(px, py) -> (px + fst deslocamento, py + snd deslocamento))
pontos)
-- Move um ponto para a nova posição
movePonto :: Point -> Point -> Point
movePonto (dx, dy) (x, y) = (x + dx, y + dy)

-- Função que substitui uma figura antiga por uma nova na lista de figuras
replaceFigura :: Figura -> Figura -> [Figura] -> [Figura]
replaceFigura _ _ [] = []
replaceFigura figAntiga figNova (f:fs)
| f == figAntiga = figNova : fs
| otherwise = f : replaceFigura figAntiga figNova fs
-- Verifica se o ponto está dentro de uma figura (círculo, retângulo ou linha)
pontoDentroFigura :: Point -> Figura -> Bool
pontoDentroFigura p (Circulo c r) = vectorLength (vectorDifference p c) <= r
pontoDentroFigura p (Retangulo p1 p2) = dentroRetangulo p p1 p2
pontoDentroFigura p (Linha pontos) = pontoNaLinha p pontos

-- Verifica se o ponto está dentro de um retângulo


dentroRetangulo :: Point -> Point -> Point -> Bool
dentroRetangulo (px, py) (x1, y1) (x2, y2) =
px >= min x1 x2 && px <= max x1 x2 &&
py >= min y1 y2 && py <= max y1 y2

-- Verifica se o ponto está próximo de uma linha (desenho livre)


pontoNaLinha :: Point -> [Point] -> Bool
pontoNaLinha _ [] = False
pontoNaLinha p [_] = False
pontoNaLinha p (p1:p2:ps) =
pontoProximoDaReta p p1 p2 || pontoNaLinha p (p2:ps)

-- Verifica se o ponto está suficientemente próximo de uma reta definida por dois
pontos
pontoProximoDaReta :: Point -> Point -> Point -> Bool
pontoProximoDaReta (px, py) (x1, y1) (x2, y2) =
let area = abs ((x2 - x1) * (py - y1) - (y2 - y1) * (px - x1))
base = vectorLength (vectorDifference (x1, y1) (x2, y2))
in base /= 0 && area / base < 0.2 -- Verifica se está a uma distância menor
que 0.2 da linha

Você também pode gostar