Fix bug in line zoning by using less ambitious algorithm

This commit is contained in:
2022-02-13 09:24:27 +00:00
parent 0a860e6f68
commit 9af636aa83
10 changed files with 65 additions and 22 deletions
+43 -3
View File
@@ -1,8 +1,9 @@
--{-# LANGUAGE TupleSections #-}
module Geometry.Zone
( ddaExt
)
where
, ddaExt'
, ddaSq
) where
import Geometry.Data
import Data.Foldable
@@ -77,10 +78,49 @@ sizeZoneOfPoint' s = fmap (divTo s)
-- | y > x = [x .. y]
-- | otherwise = [y .. x]
-- | Determines a "square" zone of points for a line
ddaSq :: Float -> V2 Float -> V2 Float -> IM.IntMap IS.IntSet
ddaSq s (V2 sx sy) (V2 ex ey) = IM.fromSet (const ys) xs
where
maxMin a b | a >= b = (a,b)
| otherwise = (b,a)
(maxx,minx) = maxMin (divTo s sx) (divTo s ex)
(maxy,miny) = maxMin (divTo s sy) (divTo s ey)
xs = IS.fromDistinctAscList [minx-1..maxx+1]
ys = IS.fromDistinctAscList [miny-1..maxy+1]
-- | Determines which horizontal and vertical lines on a grid are crossed by a
-- line. For each adds the x-y index of the square to the right or above the
-- crossed grid line. Also adds the index of the square containing the start
-- point.
ddaExt' :: Float -> V2 Float -> V2 Float -> IM.IntMap IS.IntSet
ddaExt' s sp@(V2 sx sy) ep@(V2 ex ey)
| x1 <= x2 = addsp . addys . IM.fromDistinctAscList $ zip [x1 .. x2]
$ map (IS.singleton . divTo s) [x1y,x1y+ydx..]
| otherwise = ddaExt' s ep sp
where
addsp im = let V2 x y = sizeZoneOfPoint' s sp
in insertXY im (x,y)
x1 = divTo s sx
x2 = divTo s ex
x1y = fx' sp ep $ s * fromIntegral x1
ydx = s * ydx' sp ep
addys m = add2s m ypairs
y1 = divTo s sy
y2 = divTo s ey
y1x = fy' sp ep $ s * fromIntegral y1
y2x = fy' sp ep $ s * fromIntegral y2
xdy = s * xdy' sp ep
ypairs
| y1 <= y2 = zip (map (divTo s) [y1x,y1x+xdy..])
[y1 .. y2]
| otherwise = zip (map (divTo s) [y2x,y2x+xdy..])
[y2-1 .. y1-1]
-- | Determines which horizontal and vertical lines on a grid are crossed by a
-- line. For each adds the x-y index of the square to the right or above the
-- crossed grid line. Also adds the index of the square containing the start
-- point.
-- Not correct, eg ddaExt 10 (V2 40 50) (V2 0 0)
ddaExt :: Float -> V2 Float -> V2 Float -> IM.IntMap IS.IntSet
ddaExt s sp@(V2 sx sy) ep@(V2 ex ey)
| x1 <= x2 = addsp . addys . IM.fromDistinctAscList $ zip [x1 .. x2]
@@ -89,7 +129,7 @@ ddaExt s sp@(V2 sx sy) ep@(V2 ex ey)
$ map (IS.singleton . divTo s) [x2y,x2y+ydx..]
where
addsp im = let V2 x y = sizeZoneOfPoint' s sp
in insertXY im (x,y)
in insertXY im (x,y)
x1 = divTo s sx
x2 = divTo s ex
x1y = fx' sp ep $ s * fromIntegral x1