我实现了一种算法,给出了应该绘制的点的列表,以便在两点之间得到一条线。请注意:它只在原点(0,0)位于左上角的坐标系中工作。
我想了解一下我的Haskell代码,它能在所使用的语言结构方面得到改进吗?它能更易读,更直接吗?
module DrawLine where
data Point = Point Float Float deriving (Show)
getRange :: Int -> Int -> [Int]
getRange a b
| a <= b = [a..b]
| otherwise = [b..a]
{-|
- Get the slope of a line described by the two points received as arguments
-}
getSlope :: Point -> Point -> Float
getSlope (Point x1 y1) (Point x2 y2) = (y2-y1)/(x2-x1)
{-|
- Get a list of points where pixels should be filled to draw a line
- (Inspired from Bresenham's line algorithm)
- Takes two Point arguments representing the end points of the line, the points
- will be located on a line between these two points
-}
getLinePoints :: Point -> Point -> [Point]
getLinePoints f@(Point fx fy) l@(Point lx ly)
-- vertical line
| fx == lx = [(Point fx (fromIntegral y)) | y <- getRange (round fy) (round ly)]
| otherwise =
-- generate points by mapping on the "longer side" of the line
if m > 1.0 || m < -1.0 then
-- the rise if higher than the run
map (\y ->
(Point
((1/m) * ((fromIntegral y) - fy) + fx)
(fromIntegral y)
)
)
(getRange (round fy) (round ly))
else
map (\x ->
(Point
(fromIntegral x)
(m * ((fromIntegral x) - fx) + fy)
)
)
(getRange (round fx) (round lx))
where
m = getSlope f l 发布于 2014-03-25 22:58:41
思想。
定义Line类型并将getLinePoints重命名为mkLine。一个点的列表可能代表任何东西,但Line [Points]却暗示着行内的Points。在可能的情况下,让类型系统为您工作。当然,你可以变得可爱,拥有Line (m -> x -> b -> [Points])或List Point Point。
您可以为Point和行类型定义Eq和Ord实例。
如果getSlope被传递给一条垂直线,该怎么办?它应该使用Maybe吗?
我会把非垂直线支持移动到它自己的功能中。也许还添加了一个水平线函数。
为什么对垂直行使用列表理解,而对其他类型的行使用map?这一切都可以通过理解来完成。
https://codereview.stackexchange.com/questions/38358
复制相似问题