Digital line zoning
This commit is contained in:
+53
-10
@@ -3,8 +3,12 @@ module Geometry.Zone
|
||||
( ddaExt
|
||||
, ddaExt'
|
||||
, ddaSq
|
||||
, ddaSqStream
|
||||
-- , ddaSqStream
|
||||
, ddaStream
|
||||
, ddaStreamX
|
||||
, ddaStreamY
|
||||
, xIntercepts
|
||||
, yIntercepts
|
||||
) where
|
||||
import Geometry.Data
|
||||
|
||||
@@ -13,6 +17,7 @@ import qualified Streaming.Prelude as S
|
||||
import Data.Foldable
|
||||
import qualified Data.IntMap.Strict as IM
|
||||
import qualified Data.IntSet as IS
|
||||
--import Control.Monad
|
||||
|
||||
--foldl2'
|
||||
-- :: (b -> a -> a -> b)
|
||||
@@ -62,6 +67,17 @@ divTo :: Float -> Float -> Int
|
||||
{-# INLINE divTo #-}
|
||||
divTo s = floor . (/s)
|
||||
|
||||
modTo :: Float -> Float -> Float
|
||||
modTo s x = x - s * fromIntegral (divTo s x)
|
||||
|
||||
--remTo :: Float -> Float -> Float
|
||||
--remTo s x = x - s * fromIntegral (quotTo s x)
|
||||
--
|
||||
--quotTo :: Float -> Float -> Int
|
||||
--{-# INLINE quotTo #-}
|
||||
--quotTo s = truncate . (/s)
|
||||
|
||||
|
||||
--flipV :: Point2 -> Point2
|
||||
--{-# INLINE flipV #-}
|
||||
--flipV (V2 a b) = V2 b a
|
||||
@@ -93,13 +109,13 @@ ddaSq s (V2 sx sy) (V2 ex ey) = IM.fromSet (const ys) xs
|
||||
xs = IS.fromDistinctAscList [minx-1..maxx+1]
|
||||
ys = IS.fromDistinctAscList [miny-1..maxy+1]
|
||||
|
||||
ddaSqStream :: Monad m => Float -> V2 Float -> V2 Float -> Stream (Of (Int,Int)) m ()
|
||||
ddaSqStream s (V2 sx sy) (V2 ex ey) = S.each [(x,y) | x <- [minx..maxx], y <- [miny..maxy]]
|
||||
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)
|
||||
--ddaSqStream :: Monad m => Float -> V2 Float -> V2 Float -> Stream (Of (V2 Int)) m ()
|
||||
--ddaSqStream s (V2 sx sy) (V2 ex ey) = S.each [V2 x y | x <- [minx..maxx], y <- [miny..maxy]]
|
||||
-- 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)
|
||||
|
||||
-- | 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
|
||||
@@ -129,8 +145,35 @@ ddaExt' s sp@(V2 sx sy) ep@(V2 ex ey)
|
||||
| otherwise = zip (map (divTo s) [y2x,y2x+xdy..])
|
||||
[y2-1 .. y1-1]
|
||||
ddaStream :: Float -> Point2 -> Point2 -> Stream (Of (V2 Int)) Identity ()
|
||||
ddaStream s sp _ -- @(V2 sx sy) ep@(V2 ex ey)
|
||||
= S.yield $ sizeZoneOfPoint' s sp
|
||||
ddaStream s sp ep = S.map (sizeZoneOfPoint' s)
|
||||
$ S.yield sp
|
||||
<> xIntercepts s sp ep
|
||||
<> yIntercepts s sp ep
|
||||
|
||||
ddaStreamX :: Float -> Point2 -> Point2 -> Stream (Of (V2 Int)) Identity ()
|
||||
ddaStreamX s sp ep = S.map (sizeZoneOfPoint' s) $ xIntercepts s sp ep
|
||||
|
||||
ddaStreamY :: Float -> Point2 -> Point2 -> Stream (Of (V2 Int)) Identity ()
|
||||
ddaStreamY s sp ep = S.map (sizeZoneOfPoint' s) $ yIntercepts s sp ep
|
||||
|
||||
xIntercepts :: Float -> Point2 -> Point2 -> Stream (Of Point2) Identity ()
|
||||
xIntercepts s (V2 sx sy) (V2 ex ey)
|
||||
| xdx == 0 = mempty
|
||||
| xdx > 0 = S.each $ zipWith V2 [sx',sx'+xdx*50..ex] [sy',sy'+ydx*50..ey]
|
||||
| otherwise = S.each $ zipWith V2 [sx'-50,sx'+xdx*50-50..ex-50] [sy',sy'+ydx*50..ey]
|
||||
where
|
||||
xdx = signum (ex - sx)
|
||||
ydx = (ey - sy) / abs (ex - sx)
|
||||
|
||||
sy' = sy + ydx * abs (sx - sx')
|
||||
sx' | xdx < 0 = sx - modTo s sx
|
||||
| otherwise = s + sx - modTo s sx
|
||||
|
||||
yIntercepts :: Float -> Point2 -> Point2 -> Stream (Of Point2) Identity ()
|
||||
yIntercepts s sp ep = S.map f $ xIntercepts s (f sp) (f ep)
|
||||
where
|
||||
f (V2 x y) = V2 y x
|
||||
|
||||
|
||||
-- | 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
|
||||
|
||||
Reference in New Issue
Block a user