Improve line zoning
This commit is contained in:
+5
-5
@@ -74,7 +74,7 @@ wallNormal wl = normalizeV . vNormal $ a -.- b
|
|||||||
wallsOnLine :: Point2 -> Point2 -> IM.IntMap Wall -> [Wall]
|
wallsOnLine :: Point2 -> Point2 -> IM.IntMap Wall -> [Wall]
|
||||||
wallsOnLine p1 p2 ws = hitWalls
|
wallsOnLine p1 p2 ws = hitWalls
|
||||||
where
|
where
|
||||||
hitPoint w = uncurry (intersectSegSeg' p1 p2) (_wlLine w)
|
hitPoint w = uncurry (intersectSegSeg p1 p2) (_wlLine w)
|
||||||
hitWalls = filter (isJust . hitPoint) (IM.elems ws)
|
hitWalls = filter (isJust . hitPoint) (IM.elems ws)
|
||||||
|
|
||||||
wallsOnCirc :: Point2 -> Float -> IM.IntMap Wall -> IM.IntMap Wall
|
wallsOnCirc :: Point2 -> Float -> IM.IntMap Wall -> IM.IntMap Wall
|
||||||
@@ -252,7 +252,7 @@ collidePointFF = undefined
|
|||||||
-- -> Maybe (Point2,(Maybe (Point2,StdGen),Int))
|
-- -> Maybe (Point2,(Maybe (Point2,StdGen),Int))
|
||||||
--collidePointFF p1 p2 g ff = fmap f ip
|
--collidePointFF p1 p2 g ff = fmap f ip
|
||||||
-- where (p3:p4:_) = _ffLine ff
|
-- where (p3:p4:_) = _ffLine ff
|
||||||
-- ip = intersectSegSeg' p1 p2 p3 p4
|
-- ip = intersectSegSeg p1 p2 p3 p4
|
||||||
-- ref = (_ffDeflect ff) <*> Just g <*> Just (p2 -.- p1) <*> Just ff
|
-- ref = (_ffDeflect ff) <*> Just g <*> Just (p2 -.- p1) <*> Just ff
|
||||||
-- f p = (p, (ref, _ffID ff))
|
-- f p = (p, (ref, _ffID ff))
|
||||||
--
|
--
|
||||||
@@ -267,7 +267,7 @@ collideCircWalls' p1 p2 rad ws
|
|||||||
((, reflectInParam 0.5 (x -.- y) (p2 -.- p1))
|
((, reflectInParam 0.5 (x -.- y) (p2 -.- p1))
|
||||||
. (+.+ errorNormalizeV 40 (vNormal (x -.- y)))
|
. (+.+ errorNormalizeV 40 (vNormal (x -.- y)))
|
||||||
)
|
)
|
||||||
(intersectSegSeg' p1 p2 x y)
|
(intersectSegSeg p1 p2 x y)
|
||||||
)
|
)
|
||||||
. shiftByRad . _wlLine
|
. shiftByRad . _wlLine
|
||||||
) ws
|
) ws
|
||||||
@@ -288,7 +288,7 @@ collideCircWalls' p1 p2 rad ws
|
|||||||
collidePointLines :: Point2 -> Point2 -> [Wall'] -> Maybe (Point2,Point2)
|
collidePointLines :: Point2 -> Point2 -> [Wall'] -> Maybe (Point2,Point2)
|
||||||
collidePointLines p1 p2 ws
|
collidePointLines p1 p2 ws
|
||||||
= safeMinimumOn f
|
= safeMinimumOn f
|
||||||
$ mapMaybe (( \(x,y) -> intersectSegSeg' p1 p2 x y <&> ( , vNormal $ x -.- y ) )
|
$ mapMaybe (( \(x,y) -> intersectSegSeg p1 p2 x y <&> ( , vNormal $ x -.- y ) )
|
||||||
. _wlLine') ws
|
. _wlLine') ws
|
||||||
where
|
where
|
||||||
f (a,_) = magV (p1 -.- a)
|
f (a,_) = magV (p1 -.- a)
|
||||||
@@ -298,7 +298,7 @@ collidePointLines p1 p2 ws
|
|||||||
collidePointWallsNorm :: Point2 -> Point2 -> IM.IntMap Wall -> Maybe (Point2,Point2)
|
collidePointWallsNorm :: Point2 -> Point2 -> IM.IntMap Wall -> Maybe (Point2,Point2)
|
||||||
collidePointWallsNorm p1 p2 ws
|
collidePointWallsNorm p1 p2 ws
|
||||||
= safeMinimumOn f
|
= safeMinimumOn f
|
||||||
$ IM.mapMaybe (( \(x,y) -> intersectSegSeg' p1 p2 x y <&> ( , vNormal $ x -.- y ) )
|
$ IM.mapMaybe (( \(x,y) -> intersectSegSeg p1 p2 x y <&> ( , vNormal $ x -.- y ) )
|
||||||
. _wlLine) ws
|
. _wlLine) ws
|
||||||
where
|
where
|
||||||
f (a,_) = magV (p1 -.- a)
|
f (a,_) = magV (p1 -.- a)
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ hitPointLines
|
|||||||
hitPointLines p1 p2
|
hitPointLines p1 p2
|
||||||
= safeMinimumOn (dist p1 . fst)
|
= safeMinimumOn (dist p1 . fst)
|
||||||
. mapMaybe
|
. mapMaybe
|
||||||
(\(x,y) -> (, (x,y)) <$> intersectSegSeg' p1 p2 x y)
|
(\(x,y) -> (, (x,y)) <$> intersectSegSeg p1 p2 x y)
|
||||||
|
|
||||||
-- | looks for first collision of a point with walls
|
-- | looks for first collision of a point with walls
|
||||||
-- if found, gives point and reflection velocity
|
-- if found, gives point and reflection velocity
|
||||||
@@ -36,7 +36,7 @@ reflectPointWalls p1 p2 ws
|
|||||||
fmap ( (, reflectIn (x -.- y) (p2 -.- p1))
|
fmap ( (, reflectIn (x -.- y) (p2 -.- p1))
|
||||||
. (+.+ errorNormalizeV 39 (vNormal (x -.- y)))
|
. (+.+ errorNormalizeV 39 (vNormal (x -.- y)))
|
||||||
)
|
)
|
||||||
(intersectSegSeg' p1 p2 x y)
|
(intersectSegSeg p1 p2 x y)
|
||||||
)
|
)
|
||||||
. _wlLine) ws
|
. _wlLine) ws
|
||||||
-- | Looks for first collision of a point with walls.
|
-- | Looks for first collision of a point with walls.
|
||||||
@@ -52,43 +52,43 @@ reflectPointWallsDamped dfact p1 p2 ws
|
|||||||
$ IM.mapMaybe
|
$ IM.mapMaybe
|
||||||
(( \(x,y) -> fmap ((, reflectInParam dfact (x -.- y) (p2 -.- p1))
|
(( \(x,y) -> fmap ((, reflectInParam dfact (x -.- y) (p2 -.- p1))
|
||||||
. (+.+ errorNormalizeV 40 (vNormal (x -.- y))))
|
. (+.+ errorNormalizeV 40 (vNormal (x -.- y))))
|
||||||
(intersectSegSeg' p1 p2 x y))
|
(intersectSegSeg p1 p2 x y))
|
||||||
. _wlLine
|
. _wlLine
|
||||||
) ws
|
) ws
|
||||||
-- | Test if a point collides with walls
|
-- | Test if a point collides with walls
|
||||||
pointHitsWalls :: Point2 -> Point2 -> IM.IntMap Wall -> Bool
|
pointHitsWalls :: Point2 -> Point2 -> IM.IntMap Wall -> Bool
|
||||||
pointHitsWalls p1 p2
|
pointHitsWalls p1 p2
|
||||||
= any $ isJust . uncurry (intersectSegSeg' p1 p2) . _wlLine
|
= any $ isJust . uncurry (intersectSegSeg p1 p2) . _wlLine
|
||||||
-- | Test if there something blocking a walk
|
-- | Test if there something blocking a walk
|
||||||
collidePointWalkable :: Point2 -> Point2 -> IM.IntMap Wall -> Bool
|
collidePointWalkable :: Point2 -> Point2 -> IM.IntMap Wall -> Bool
|
||||||
collidePointWalkable p1 p2 ws
|
collidePointWalkable p1 p2 ws
|
||||||
= any (isJust . uncurry (intersectSegSeg' p1 p2) . _wlLine)
|
= any (isJust . uncurry (intersectSegSeg p1 p2) . _wlLine)
|
||||||
$ IM.filter (fromMaybe True . (^? doorPathable)) ws
|
$ IM.filter (fromMaybe True . (^? doorPathable)) ws
|
||||||
|
|
||||||
furthestPointWalkable :: Point2 -> Point2 -> IM.IntMap Wall -> Point2
|
furthestPointWalkable :: Point2 -> Point2 -> IM.IntMap Wall -> Point2
|
||||||
furthestPointWalkable p1 p2 ws
|
furthestPointWalkable p1 p2 ws
|
||||||
= fromMaybe p2
|
= fromMaybe p2
|
||||||
. safeMinimumOn (dist p1)
|
. safeMinimumOn (dist p1)
|
||||||
$ IM.mapMaybe ( uncurry (intersectSegSeg' p1 p2) . _wlLine) ws
|
$ IM.mapMaybe ( uncurry (intersectSegSeg p1 p2) . _wlLine) ws
|
||||||
|
|
||||||
collidePointIndirect :: Point2 -> Point2 -> IM.IntMap Wall -> Maybe Point2
|
collidePointIndirect :: Point2 -> Point2 -> IM.IntMap Wall -> Maybe Point2
|
||||||
{-# INLINE collidePointIndirect #-}
|
{-# INLINE collidePointIndirect #-}
|
||||||
collidePointIndirect p1 p2 ws
|
collidePointIndirect p1 p2 ws
|
||||||
= safeMinimumOn (dist p1)
|
= safeMinimumOn (dist p1)
|
||||||
. IM.mapMaybe ( uncurry (intersectSegSeg' p1 p2) . _wlLine)
|
. IM.mapMaybe ( uncurry (intersectSegSeg p1 p2) . _wlLine)
|
||||||
$ IM.filter (not . _wlIsSeeThrough) ws
|
$ IM.filter (not . _wlIsSeeThrough) ws
|
||||||
{- | Checks to see whether someone can fire bullets effectively between two points.
|
{- | Checks to see whether someone can fire bullets effectively between two points.
|
||||||
- Not sure if this needs vision as well, need to make this uniform. -}
|
- Not sure if this needs vision as well, need to make this uniform. -}
|
||||||
collidePointFire :: Point2 -> Point2 -> IM.IntMap Wall -> Maybe Point2
|
collidePointFire :: Point2 -> Point2 -> IM.IntMap Wall -> Maybe Point2
|
||||||
collidePointFire p1 p2 ws
|
collidePointFire p1 p2 ws
|
||||||
= safeMinimumOn (dist p1)
|
= safeMinimumOn (dist p1)
|
||||||
. IM.mapMaybe ( uncurry (intersectSegSeg' p1 p2) . _wlLine )
|
. IM.mapMaybe ( uncurry (intersectSegSeg p1 p2) . _wlLine )
|
||||||
$ IM.filter (\wl -> not (_wlIsSeeThrough wl && isJust (wl ^? blHP))) ws
|
$ IM.filter (\wl -> not (_wlIsSeeThrough wl && isJust (wl ^? blHP))) ws
|
||||||
{- | Checks to see whether someone can fire bullets effectively between two points.
|
{- | Checks to see whether someone can fire bullets effectively between two points.
|
||||||
- Not sure if this needs vision as well, need to make this uniform. -}
|
- Not sure if this needs vision as well, need to make this uniform. -}
|
||||||
collidePointFireVision :: Point2 -> Point2 -> IM.IntMap Wall -> Bool
|
collidePointFireVision :: Point2 -> Point2 -> IM.IntMap Wall -> Bool
|
||||||
collidePointFireVision p1 p2 ws
|
collidePointFireVision p1 p2 ws
|
||||||
= any ( isJust . uncurry (intersectSegSeg' p1 p2) . _wlLine)
|
= any ( isJust . uncurry (intersectSegSeg p1 p2) . _wlLine)
|
||||||
$ IM.filter notBlockWindow ws
|
$ IM.filter notBlockWindow ws
|
||||||
where
|
where
|
||||||
notBlockWindow wl = case wl ^? blHP of
|
notBlockWindow wl = case wl ^? blHP of
|
||||||
|
|||||||
+12
-9
@@ -5,6 +5,7 @@ module Dodge.Base.Zone
|
|||||||
import Dodge.Data
|
import Dodge.Data
|
||||||
import Dodge.Base.Window
|
import Dodge.Base.Window
|
||||||
import Geometry
|
import Geometry
|
||||||
|
import Geometry.Zone
|
||||||
|
|
||||||
import Data.Maybe
|
import Data.Maybe
|
||||||
import Data.List
|
import Data.List
|
||||||
@@ -73,14 +74,16 @@ zoneOfLine (V2 aa ab) (V2 ba bb)
|
|||||||
f (x,y) = [(p,r) | p <-[x-1,x,x+1] , r<-[y-1,y,y+1]]
|
f (x,y) = [(p,r) | p <-[x-1,x,x+1] , r<-[y-1,y,y+1]]
|
||||||
|
|
||||||
zoneOfLineIntMap :: Point2 -> Point2 -> IM.IntMap IS.IntSet
|
zoneOfLineIntMap :: Point2 -> Point2 -> IM.IntMap IS.IntSet
|
||||||
{-# INLINE zoneOfLineIntMap #-}
|
--{-# INLINE zoneOfLineIntMap #-}
|
||||||
zoneOfLineIntMap a b = expandLine $ digitalLine (x-1,y-1) (x'-1,y'-1)
|
zoneOfLineIntMap = ddaExt zoneSize
|
||||||
where
|
--zoneOfLineIntMap a b = expandLine $ digitalLine (x-1,y-1) (x'-1,y'-1)
|
||||||
(x,y) = zoneOfPoint a
|
-- where
|
||||||
(x',y') = zoneOfPoint b
|
-- (x,y) = zoneOfPoint a
|
||||||
|
-- (x',y') = zoneOfPoint b
|
||||||
|
|
||||||
|
|
||||||
expandLine :: [(Int,Int)] -> IM.IntMap IS.IntSet
|
expandLine :: [(Int,Int)] -> IM.IntMap IS.IntSet
|
||||||
{-# INLINE expandLine #-}
|
--{-# INLINE expandLine #-}
|
||||||
expandLine xs = IM.map expandSet
|
expandLine xs = IM.map expandSet
|
||||||
$ IM.unionsWith IS.union [im, IM.mapKeysMonotonic (+1) im, IM.mapKeysMonotonic (+2) im]
|
$ IM.unionsWith IS.union [im, IM.mapKeysMonotonic (+1) im, IM.mapKeysMonotonic (+2) im]
|
||||||
where
|
where
|
||||||
@@ -172,10 +175,10 @@ lookLookups xs z = mapMaybe (flip (uncurry lookLookup) z) xs
|
|||||||
-- there is certainly a problem somewhere here: it may be in the zoning, or
|
-- there is certainly a problem somewhere here: it may be in the zoning, or
|
||||||
-- within this function
|
-- within this function
|
||||||
wallsAlongLine :: Point2 -> Point2 -> World -> IM.IntMap Wall
|
wallsAlongLine :: Point2 -> Point2 -> World -> IM.IntMap Wall
|
||||||
{-# INLINE wallsAlongLine #-}
|
--{-# INLINE wallsAlongLine #-}
|
||||||
wallsAlongLine a b w = IM.foldrWithKey' g IM.empty kps
|
wallsAlongLine a b w = IM.foldlWithKey' g IM.empty kps
|
||||||
where
|
where
|
||||||
g x s = IM.union (IM.unions (IM.restrictKeys (f x $ _wallsZone w) s))
|
g m x s = IM.union (IM.unions (IM.restrictKeys (f x $ _wallsZone w) s)) m
|
||||||
kps = zoneOfLineIntMap a b
|
kps = zoneOfLineIntMap a b
|
||||||
f i m = case IM.lookup i m of
|
f i m = case IM.lookup i m of
|
||||||
Just val -> val
|
Just val -> val
|
||||||
|
|||||||
@@ -23,6 +23,6 @@ removePathsCrossing a b w = set pathGraph newGraph $ set pathGraph' pg'
|
|||||||
$ set pathPoints (foldr insertPoint IM.empty (labNodes newGraph))
|
$ set pathPoints (foldr insertPoint IM.empty (labNodes newGraph))
|
||||||
w
|
w
|
||||||
where
|
where
|
||||||
pg' = filter (isNothing . uncurry (intersectSegSeg' a b)) $ _pathGraph' w
|
pg' = filter (isNothing . uncurry (intersectSegSeg a b)) $ _pathGraph' w
|
||||||
insertPoint pp@(_,V2 x y) = insertInZoneWith (floorHun x) (floorHun y) (++) [pp]
|
insertPoint pp@(_,V2 x y) = insertInZoneWith (floorHun x) (floorHun y) (++) [pp]
|
||||||
newGraph = pairsToGraph dist pg'
|
newGraph = pairsToGraph dist pg'
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ addButtonDoor c btp btr a b w = over buttons (IM.insert bid bt)
|
|||||||
bid = IM.newKey $ _buttons w
|
bid = IM.newKey $ _buttons w
|
||||||
cond w' = BtNoLabel == _btState (_buttons w' IM.! bid)
|
cond w' = BtNoLabel == _btState (_buttons w' IM.! bid)
|
||||||
bt = (makeButton c eff) {_btPos = btp, _btRot = btr, _btID = bid}
|
bt = (makeButton c eff) {_btPos = btp, _btRot = btr, _btID = bid}
|
||||||
(newGraphPairs,removedPairs) = partition (isNothing . uncurry (intersectSegSeg' a b))
|
(newGraphPairs,removedPairs) = partition (isNothing . uncurry (intersectSegSeg a b))
|
||||||
$ _pathGraph' w
|
$ _pathGraph' w
|
||||||
newGraph = pairsToGraph dist newGraphPairs
|
newGraph = pairsToGraph dist newGraphPairs
|
||||||
insertPoint pp@(_,V2 x y) = insertInZoneWith (floorHun x) (floorHun y) (++) [pp]
|
insertPoint pp@(_,V2 x y) = insertInZoneWith (floorHun x) (floorHun y) (++) [pp]
|
||||||
@@ -49,7 +49,7 @@ addSwitchDoor c btp btr a b w = over buttons (IM.insert bid bt)
|
|||||||
bid = IM.newKey $ _buttons w
|
bid = IM.newKey $ _buttons w
|
||||||
cond w' = BtOn == _btState (_buttons w' IM.! bid)
|
cond w' = BtOn == _btState (_buttons w' IM.! bid)
|
||||||
bt = (makeSwitch c openDoor closeDoor) {_btPos = btp, _btRot = btr, _btID = bid}
|
bt = (makeSwitch c openDoor closeDoor) {_btPos = btp, _btRot = btr, _btID = bid}
|
||||||
(newGraphPairs,removedPairs) = partition (isNothing . uncurry (intersectSegSeg' a b))
|
(newGraphPairs,removedPairs) = partition (isNothing . uncurry (intersectSegSeg a b))
|
||||||
$ _pathGraph' w
|
$ _pathGraph' w
|
||||||
newGraph = pairsToGraph dist newGraphPairs
|
newGraph = pairsToGraph dist newGraphPairs
|
||||||
insertPoint pp@(_,V2 x y) = insertInZoneWith (floorHun x) (floorHun y) (++) [pp]
|
insertPoint pp@(_,V2 x y) = insertInZoneWith (floorHun x) (floorHun y) (++) [pp]
|
||||||
|
|||||||
@@ -121,7 +121,7 @@ wallShadowsToDraw w = filter (fromMaybe True . (^? blVisible))
|
|||||||
-- towards the center of sight
|
-- towards the center of sight
|
||||||
lineOnScreenCone :: World -> Point2 -> Point2 -> Bool
|
lineOnScreenCone :: World -> Point2 -> Point2 -> Bool
|
||||||
lineOnScreenCone w p1 p2 = errorPointInPolygon 8 p1 sp || errorPointInPolygon 9 p2 sp
|
lineOnScreenCone w p1 p2 = errorPointInPolygon 8 p1 sp || errorPointInPolygon 9 p2 sp
|
||||||
|| any (isJust . uncurry (intersectSegSeg' p1 p2)) sps
|
|| any (isJust . uncurry (intersectSegSeg p1 p2)) sps
|
||||||
where
|
where
|
||||||
sp' = screenPolygon w
|
sp' = screenPolygon w
|
||||||
vp = _cameraViewFrom w
|
vp = _cameraViewFrom w
|
||||||
@@ -132,7 +132,7 @@ lineOnScreenCone w p1 p2 = errorPointInPolygon 8 p1 sp || errorPointInPolygon 9
|
|||||||
|
|
||||||
lineOnScreen :: World -> Point2 -> Point2 -> Bool
|
lineOnScreen :: World -> Point2 -> Point2 -> Bool
|
||||||
lineOnScreen w p1 p2 = errorPointInPolygon 8 p1 sp || errorPointInPolygon 9 p2 sp
|
lineOnScreen w p1 p2 = errorPointInPolygon 8 p1 sp || errorPointInPolygon 9 p2 sp
|
||||||
|| any (isJust . uncurry (intersectSegSeg' p1 p2)) sps
|
|| any (isJust . uncurry (intersectSegSeg p1 p2)) sps
|
||||||
where
|
where
|
||||||
sp = screenPolygon w
|
sp = screenPolygon w
|
||||||
sps = zip sp (tail sp ++ [head sp])
|
sps = zip sp (tail sp ++ [head sp])
|
||||||
@@ -160,7 +160,7 @@ extendConeToScreenEdge w c (x,y) = orderPolygon $ wallScreenIntersect ++ [x,y] +
|
|||||||
where
|
where
|
||||||
borderPs = mapMaybe (intersectLinefromScreen w c) [x,y]
|
borderPs = mapMaybe (intersectLinefromScreen w c) [x,y]
|
||||||
cornerPs = filter (pointIsInCone c (x,y)) $ screenPolygon w
|
cornerPs = filter (pointIsInCone c (x,y)) $ screenPolygon w
|
||||||
wallScreenIntersect = mapMaybe (uncurry $ intersectSegSeg' y ((2*.*y) -.- x))
|
wallScreenIntersect = mapMaybe (uncurry $ intersectSegSeg y ((2*.*y) -.- x))
|
||||||
. makeLoopPairs $ screenPolygon w
|
. makeLoopPairs $ screenPolygon w
|
||||||
|
|
||||||
rectangleSolid :: Float -> Float -> Picture
|
rectangleSolid :: Float -> Float -> Picture
|
||||||
|
|||||||
+1
-1
@@ -226,5 +226,5 @@ visibleWalls p1 p2 ws
|
|||||||
. map f
|
. map f
|
||||||
$ IM.toList ws
|
$ IM.toList ws
|
||||||
where
|
where
|
||||||
f (i,wl) = (uncurry intersectSegSeg' (_wlLine wl) p1 p2, (i,wl))
|
f (i,wl) = (uncurry intersectSegSeg (_wlLine wl) p1 p2, (i,wl))
|
||||||
|
|
||||||
|
|||||||
@@ -105,11 +105,11 @@ checkPushThroughs cp1 wls cp2
|
|||||||
|
|
||||||
checkPushThrough :: Point2 -> Point2 -> (Point2,Point2) -> Maybe Point2
|
checkPushThrough :: Point2 -> Point2 -> (Point2,Point2) -> Maybe Point2
|
||||||
checkPushThrough cp1 cp2 (wp1,wp2)
|
checkPushThrough cp1 cp2 (wp1,wp2)
|
||||||
| isPushedThrough = intersectSegSeg' cp1 cp2 wp1 wp2
|
| isPushedThrough = intersectSegSeg cp1 cp2 wp1 wp2
|
||||||
| otherwise = Nothing
|
| otherwise = Nothing
|
||||||
where
|
where
|
||||||
--norm = errorNormalizeV 61 $ vNormal (wp1 -.- wp2)
|
--norm = errorNormalizeV 61 $ vNormal (wp1 -.- wp2)
|
||||||
--wp1' = (rad *.* norm) +.+ wp1
|
--wp1' = (rad *.* norm) +.+ wp1
|
||||||
--wp2' = (rad *.* norm) +.+ wp2
|
--wp2' = (rad *.* norm) +.+ wp2
|
||||||
--newP = errorClosestPointOnLine 5 wp1' wp2' cp2
|
--newP = errorClosestPointOnLine 5 wp1' wp2' cp2
|
||||||
isPushedThrough = isRHS wp1 wp2 cp2 && isJust (intersectSegSeg' cp1 cp2 wp1 wp2)
|
isPushedThrough = isRHS wp1 wp2 cp2 && isJust (intersectSegSeg cp1 cp2 wp1 wp2)
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ thingsHit sp ep w
|
|||||||
Just val -> val
|
Just val -> val
|
||||||
_ -> IM.empty
|
_ -> IM.empty
|
||||||
wls = zip (map (fromJust . hitPoint) hitWls) (map E3x2 hitWls)
|
wls = zip (map (fromJust . hitPoint) hitWls) (map E3x2 hitWls)
|
||||||
hitPoint w' = uncurry (intersectSegSeg' sp ep) (_wlLine w')
|
hitPoint w' = uncurry (intersectSegSeg sp ep) (_wlLine w')
|
||||||
hitFFs = mapMaybe (collidePointFF sp ep (_randGen w)) (IM.elems $ _forceFields w)
|
hitFFs = mapMaybe (collidePointFF sp ep (_randGen w)) (IM.elems $ _forceFields w)
|
||||||
ffs = map (\(p,(_,i)) -> (p, E3x3 $ _forceFields w IM.! i)) hitFFs
|
ffs = map (\(p,(_,i)) -> (p, E3x3 $ _forceFields w IM.! i)) hitFFs
|
||||||
{- List objects that appear on a line.
|
{- List objects that appear on a line.
|
||||||
@@ -76,7 +76,7 @@ thingsHitLongLine sp ep w
|
|||||||
crPs = map (\cr -> ssaTriPoint ep (_crPos cr) sp (_crRad cr)) hitCrs
|
crPs = map (\cr -> ssaTriPoint ep (_crPos cr) sp (_crRad cr)) hitCrs
|
||||||
wls = zip (map (fromJust . hitPoint) hitWls) (map E3x2 hitWls)
|
wls = zip (map (fromJust . hitPoint) hitWls) (map E3x2 hitWls)
|
||||||
hitWls = wallsOnLine sp ep $ wallsAlongLine sp ep w
|
hitWls = wallsOnLine sp ep $ wallsAlongLine sp ep w
|
||||||
hitPoint wl = uncurry (intersectSegSeg' sp ep) (_wlLine wl)
|
hitPoint wl = uncurry (intersectSegSeg sp ep) (_wlLine wl)
|
||||||
hitFFs = mapMaybe (collidePointFF sp ep (_randGen w)) (IM.elems $ _forceFields w)
|
hitFFs = mapMaybe (collidePointFF sp ep (_randGen w)) (IM.elems $ _forceFields w)
|
||||||
ffs = map (\(p,(_,i)) -> (p, E3x3 $ _forceFields w IM.! i)) hitFFs
|
ffs = map (\(p,(_,i)) -> (p, E3x3 $ _forceFields w IM.! i)) hitFFs
|
||||||
|
|
||||||
|
|||||||
+6
-47
@@ -15,6 +15,7 @@ module Geometry
|
|||||||
, module Geometry.Bezier
|
, module Geometry.Bezier
|
||||||
, module Geometry.Vector
|
, module Geometry.Vector
|
||||||
, module Geometry.LHS
|
, module Geometry.LHS
|
||||||
|
--, module Geometry.Zone
|
||||||
)
|
)
|
||||||
where
|
where
|
||||||
import Geometry.Data
|
import Geometry.Data
|
||||||
@@ -22,11 +23,9 @@ import Geometry.Intersect
|
|||||||
import Geometry.Bezier
|
import Geometry.Bezier
|
||||||
import Geometry.Vector
|
import Geometry.Vector
|
||||||
import Geometry.LHS
|
import Geometry.LHS
|
||||||
|
--import Geometry.Zone
|
||||||
|
|
||||||
--import Data.Function
|
|
||||||
import Data.List
|
import Data.List
|
||||||
import Data.Maybe
|
|
||||||
--import Control.Applicative
|
|
||||||
-- | Return a point a distance away from a first point towards a second point.
|
-- | Return a point a distance away from a first point towards a second point.
|
||||||
-- Does not go past the second point.
|
-- Does not go past the second point.
|
||||||
alongSegBy :: Float -> Point2 -> Point2 -> Point2
|
alongSegBy :: Float -> Point2 -> Point2 -> Point2
|
||||||
@@ -191,48 +190,6 @@ doublePair (x,y) = [(x,y),(y,x)]
|
|||||||
|
|
||||||
doubleV2 :: V2 a -> [V2 a]
|
doubleV2 :: V2 a -> [V2 a]
|
||||||
doubleV2 (V2 x y) = [V2 x y,V2 y x]
|
doubleV2 (V2 x y) = [V2 x y,V2 y x]
|
||||||
|
|
||||||
-- | Test whether two polygons intersect by testing the intersection of each
|
|
||||||
-- consecutive pair of points.
|
|
||||||
--polysIntersect :: [Point2] -> [Point2] -> Bool
|
|
||||||
--{-# INLINE polysIntersect #-}
|
|
||||||
--polysIntersect (p:ps) (q:qs)
|
|
||||||
-- -- = any isJust $ (\(V2 a b) (V2 c d) -> myIntersectSegSeg a b c d) <$> pairs1 <*> pairs2
|
|
||||||
-- = or $ (\(V2 a b) (V2 c d) -> isJust $ myIntersectSegSeg a b c d) <$> pairs1 <*> pairs2
|
|
||||||
-- where
|
|
||||||
-- pairs1 = zipWith V2 (p:ps) (ps++[p])
|
|
||||||
-- pairs2 = zipWith V2 (q:qs) (qs++[q])
|
|
||||||
--polysIntersect _ _ = False
|
|
||||||
|
|
||||||
polysIntersect :: [Point2] -> [Point2] -> Bool
|
|
||||||
polysIntersect (a:b:xs) ps = go a (a:b:xs) ps
|
|
||||||
where
|
|
||||||
go x' (a':b':xs') ps' = pairPolyIntersect a' b' ps' || go x' (b':xs') ps'
|
|
||||||
go b' (a':[]) ps' = pairPolyIntersect a' b' ps'
|
|
||||||
go _ _ _ = False
|
|
||||||
polysIntersect _ _ = False
|
|
||||||
|
|
||||||
pairPolyIntersect :: Point2 -> Point2 -> [Point2] -> Bool
|
|
||||||
pairPolyIntersect a' b' (c':d':xs') = go c' a' b' (c':d':xs')
|
|
||||||
where
|
|
||||||
go x a b (c:d:xs)
|
|
||||||
| isJust $ myIntersectSegSeg a b c d = True
|
|
||||||
| otherwise = go x a b (d:xs)
|
|
||||||
go d a b (c:[]) = isJust $ myIntersectSegSeg a b c d
|
|
||||||
go _ _ _ _ = False
|
|
||||||
pairPolyIntersect _ _ _ = False
|
|
||||||
|
|
||||||
-- | Test whether two polygons intersect or if one is contained in the other.
|
|
||||||
polysOverlap :: [Point2] -> [Point2] -> Bool
|
|
||||||
polysOverlap (p:ps) (q:qs) = pointInPolygon p (q:qs)
|
|
||||||
|| pointInPolygon q (p:ps)
|
|
||||||
|| polysIntersect (p:ps) (q:qs)
|
|
||||||
polysOverlap _ _ = False
|
|
||||||
-- | Test whether any polygons from a first list intersect with any polygons from
|
|
||||||
-- a second list.
|
|
||||||
anyPolyssIntersect :: [[Point2]] -> [[Point2]] -> Bool
|
|
||||||
anyPolyssIntersect x y = or $ polysIntersect <$> x <*> y
|
|
||||||
|
|
||||||
-- split a list into triples, forms triangles from a polygon
|
-- split a list into triples, forms triangles from a polygon
|
||||||
polyToTris :: [s] -> [s]
|
polyToTris :: [s] -> [s]
|
||||||
{-# INLINE polyToTris #-}
|
{-# INLINE polyToTris #-}
|
||||||
@@ -394,10 +351,11 @@ divideLineExact x a b = map ( (a +.+ ) . ( *.* v) ) [0 , x .. d]
|
|||||||
d = dist a b
|
d = dist a b
|
||||||
v = normalizeV $ b -.- a
|
v = normalizeV $ b -.- a
|
||||||
|
|
||||||
|
|
||||||
-- | Given two pairs of Ints, returns a list of pairs of Ints that form
|
-- | Given two pairs of Ints, returns a list of pairs of Ints that form
|
||||||
-- a digital line between them.
|
-- a digital line between them.
|
||||||
digitalLine :: (Int,Int) -> (Int,Int) -> [(Int,Int)]
|
digitalLine :: (Int,Int) -> (Int,Int) -> [(Int,Int)]
|
||||||
{-# INLINE digitalLine #-}
|
--{-# INLINE digitalLine #-}
|
||||||
digitalLine (x1,y1) (x2,y2)
|
digitalLine (x1,y1) (x2,y2)
|
||||||
| abs (x1-x2) > abs (y1-y2) =
|
| abs (x1-x2) > abs (y1-y2) =
|
||||||
[ (x,( (y1-y2) * x + x1*y2 - x2*y1) `rdiv` (x1-x2) )
|
[ (x,( (y1-y2) * x + x1*y2 - x2*y1) `rdiv` (x1-x2) )
|
||||||
@@ -421,8 +379,9 @@ digitalRect (a,b) (c,d) = [(s,t) | s <- [minx .. maxx] , t <- [miny .. maxy]]
|
|||||||
miny = min b d
|
miny = min b d
|
||||||
-- | Given two Ints, creates the list of Ints between these.
|
-- | Given two Ints, creates the list of Ints between these.
|
||||||
intervalList :: Int -> Int -> [Int]
|
intervalList :: Int -> Int -> [Int]
|
||||||
|
{-# INLINE intervalList #-}
|
||||||
intervalList x y
|
intervalList x y
|
||||||
| y >= x = [x .. y]
|
| y > x = [x .. y]
|
||||||
| otherwise = reverse [y..x]
|
| otherwise = reverse [y..x]
|
||||||
-- | Create points on the circumference of a circle with maximal distance
|
-- | Create points on the circumference of a circle with maximal distance
|
||||||
-- between them.
|
-- between them.
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ polyPointsIntersect :: [Point2] -> [Point2] -> Bool
|
|||||||
polyPointsIntersect (a:b:xs) ps = go a (a:b:xs) ps
|
polyPointsIntersect (a:b:xs) ps = go a (a:b:xs) ps
|
||||||
where
|
where
|
||||||
go x' (a':b':xs') ps' = pairPolyPointsIntersect a' b' ps' || go x' (b':xs') ps'
|
go x' (a':b':xs') ps' = pairPolyPointsIntersect a' b' ps' || go x' (b':xs') ps'
|
||||||
go b' (a':[]) ps' = pairPolyPointsIntersect a' b' ps'
|
go b' [a'] ps' = pairPolyPointsIntersect a' b' ps'
|
||||||
go _ _ _ = False
|
go _ _ _ = False
|
||||||
polyPointsIntersect _ _ = False
|
polyPointsIntersect _ _ = False
|
||||||
|
|
||||||
@@ -67,7 +67,7 @@ pairPolyPointsIntersect a' b' (c':d':xs') = go c' a' b' (c':d':xs')
|
|||||||
go x a b (c:d:xs)
|
go x a b (c:d:xs)
|
||||||
| isJust $ myIntersectSegSeg a b c d = True
|
| isJust $ myIntersectSegSeg a b c d = True
|
||||||
| otherwise = go x a b (d:xs)
|
| otherwise = go x a b (d:xs)
|
||||||
go d a b (c:[]) = isJust $ myIntersectSegSeg a b c d
|
go d a b [c] = isJust $ myIntersectSegSeg a b c d
|
||||||
go _ _ _ _ = False
|
go _ _ _ _ = False
|
||||||
pairPolyPointsIntersect _ _ _ = False
|
pairPolyPointsIntersect _ _ _ = False
|
||||||
|
|
||||||
|
|||||||
@@ -18,9 +18,9 @@ intersectLineLine' (V2 x1 y1) (V2 x2 y2) (V2 x3 y3) (V2 x4 y4)
|
|||||||
den = (x1-x2)*(y3-y4) - (y1-y2)*(x3-x4)
|
den = (x1-x2)*(y3-y4) - (y1-y2)*(x3-x4)
|
||||||
t' = (x1-x3)*(y3-y4) - (y1-y3)*(x3-x4)
|
t' = (x1-x3)*(y3-y4) - (y1-y3)*(x3-x4)
|
||||||
-- | If two segments intersect, return 'Just' that point.
|
-- | If two segments intersect, return 'Just' that point.
|
||||||
intersectSegSeg' :: Point2 -> Point2 -> Point2 -> Point2 -> Maybe Point2
|
intersectSegSeg :: Point2 -> Point2 -> Point2 -> Point2 -> Maybe Point2
|
||||||
{-# INLINE intersectSegSeg' #-}
|
{-# INLINE intersectSegSeg #-}
|
||||||
intersectSegSeg' (V2 x1 y1) (V2 x2 y2) (V2 x3 y3) (V2 x4 y4)
|
intersectSegSeg (V2 x1 y1) (V2 x2 y2) (V2 x3 y3) (V2 x4 y4)
|
||||||
| den == 0 = Nothing
|
| den == 0 = Nothing
|
||||||
| den > 0 && (t' < 0 || u' < 0 || t' > den || u' > den)
|
| den > 0 && (t' < 0 || u' < 0 || t' > den || u' > den)
|
||||||
= Nothing
|
= Nothing
|
||||||
|
|||||||
@@ -0,0 +1,149 @@
|
|||||||
|
{-# LANGUAGE TupleSections #-}
|
||||||
|
module Geometry.Zone
|
||||||
|
( ddaExt
|
||||||
|
)
|
||||||
|
where
|
||||||
|
import Geometry.Data
|
||||||
|
|
||||||
|
import Data.Foldable
|
||||||
|
import qualified Data.IntMap.Strict as IM
|
||||||
|
import qualified Data.IntSet as IS
|
||||||
|
|
||||||
|
foldl2'
|
||||||
|
:: (b -> a -> a -> b)
|
||||||
|
-> b
|
||||||
|
-> [a]
|
||||||
|
-> b
|
||||||
|
foldl2' f s (t:ts) = fst $ foldl' g (s, t) ts
|
||||||
|
where
|
||||||
|
g (r,x) y = (f r x y,y)
|
||||||
|
foldl2' _ s _ = s
|
||||||
|
|
||||||
|
sortArguments
|
||||||
|
:: Ord a
|
||||||
|
=> (a -> a -> b)
|
||||||
|
-> a -> a -> b
|
||||||
|
sortArguments f x y
|
||||||
|
| x < y = f x y
|
||||||
|
| otherwise = f y x
|
||||||
|
sortArgumentsReverse
|
||||||
|
:: Ord a
|
||||||
|
=> (a -> a -> [b])
|
||||||
|
-> a -> a -> [b]
|
||||||
|
sortArgumentsReverse f x y
|
||||||
|
| x < y = f x y
|
||||||
|
| otherwise = reverse $ f y x
|
||||||
|
|
||||||
|
intervalBounds
|
||||||
|
:: Float -- ^ interval threshold
|
||||||
|
-> Float -- ^ First endpoint
|
||||||
|
-> Float -- ^ Second endpoint
|
||||||
|
-> [Float]
|
||||||
|
intervalBounds = sortArgumentsReverse . f
|
||||||
|
where
|
||||||
|
f r a b
|
||||||
|
| x > b = [a]
|
||||||
|
| otherwise = (a : [x,x+r..b])
|
||||||
|
where
|
||||||
|
x = floorTo r a + r
|
||||||
|
|
||||||
|
floorTo :: Float -> Float -> Float
|
||||||
|
floorTo r x = r * (fromIntegral ((floor $ x / r) :: Int))
|
||||||
|
|
||||||
|
ceilingTo :: Float -> Float -> Float
|
||||||
|
ceilingTo r x = r * (fromIntegral ((ceiling $ x / r) :: Int))
|
||||||
|
|
||||||
|
divTo :: Float -> Float -> Int
|
||||||
|
{-# INLINE divTo #-}
|
||||||
|
divTo s = floor . (/s)
|
||||||
|
|
||||||
|
flipV :: Point2 -> Point2
|
||||||
|
{-# INLINE flipV #-}
|
||||||
|
flipV (V2 a b) = V2 b a
|
||||||
|
|
||||||
|
applyInverted
|
||||||
|
:: (Point2 -> Point2 -> [Point2])
|
||||||
|
-> Point2 -> Point2 -> [Point2]
|
||||||
|
applyInverted f sp@(V2 sx sy) ep@(V2 ex ey)
|
||||||
|
| abs (sx-ex) > abs (sy-ey) = f sp ep
|
||||||
|
| otherwise = map flipV $ f (flipV sp) (flipV ep)
|
||||||
|
|
||||||
|
sizeZoneOfPoint' :: Float -> Point2 -> V2 Int
|
||||||
|
sizeZoneOfPoint' s = fmap (divTo s)
|
||||||
|
|
||||||
|
increasingInterval :: Int -> Int -> [Int]
|
||||||
|
increasingInterval x y
|
||||||
|
| y > x = [x .. y]
|
||||||
|
| otherwise = [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
|
||||||
|
-- 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 = addys . IM.fromDistinctAscList $ zip [x1 .. x2]
|
||||||
|
$ map (IS.singleton . divTo s) [x1y,x1y+ydx..]
|
||||||
|
| otherwise = addys . IM.fromDistinctAscList $ zip [x2-1 .. x1-1]
|
||||||
|
$ map (IS.singleton . divTo s) [x2y,x2y+ydx..]
|
||||||
|
where
|
||||||
|
x1 = divTo s sx
|
||||||
|
x2 = divTo s ex
|
||||||
|
x1y = fx' sp ep $ s * (fromIntegral x1)
|
||||||
|
x2y = fx' sp ep $ s * (fromIntegral x2)
|
||||||
|
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]
|
||||||
|
|
||||||
|
ydx' :: Point2 -> Point2 -> Float
|
||||||
|
{-# INLINE ydx' #-}
|
||||||
|
ydx' (V2 sx sy) (V2 ex ey)
|
||||||
|
| sx == ex = 0
|
||||||
|
| otherwise = (ey - sy) / (ex - sx)
|
||||||
|
xInt' :: Float -> Point2 -> Point2 -> Float
|
||||||
|
xInt' s (V2 sx _) (V2 ex _)
|
||||||
|
| ex > sx = ceilingTo s sx
|
||||||
|
| otherwise = floorTo s sx
|
||||||
|
fx' :: Point2 -> Point2 -> Float -> Float
|
||||||
|
fx' sp@(V2 sx sy) ep@(V2 _ ey) x
|
||||||
|
| sy == ey = sy
|
||||||
|
| otherwise = sy + ydx' sp ep * (x - sx)
|
||||||
|
|
||||||
|
xdy' :: Point2 -> Point2 -> Float
|
||||||
|
xdy' (V2 sx sy) (V2 ex ey)
|
||||||
|
| sy == ey = 0
|
||||||
|
| otherwise = (ex - sx) / (ey - sy)
|
||||||
|
yInt' :: Float -> Point2 -> Point2 -> Float
|
||||||
|
yInt' s (V2 _ sy) (V2 _ ey)
|
||||||
|
| ey > sy = ceilingTo s sy
|
||||||
|
| otherwise = floorTo s sy
|
||||||
|
fy' :: Point2 -> Point2 -> Float -> Float
|
||||||
|
fy' sp@(V2 sx sy) ep@(V2 ex _) y
|
||||||
|
| sx == ex = sx
|
||||||
|
| otherwise = sx + xdy' sp ep * (y - sy)
|
||||||
|
|
||||||
|
add2s :: IM.IntMap IS.IntSet -> [(Int,Int)] -> IM.IntMap IS.IntSet
|
||||||
|
{-# INLINE add2s #-}
|
||||||
|
add2s imis = foldl'
|
||||||
|
(\m (k,x) -> IM.insertWith (\_ old -> IS.insert x old) k (IS.singleton x) m)
|
||||||
|
imis
|
||||||
|
|
||||||
|
addV2s :: IM.IntMap IS.IntSet -> [V2 Int] -> IM.IntMap IS.IntSet
|
||||||
|
{-# INLINE addV2s #-}
|
||||||
|
addV2s imis = foldl'
|
||||||
|
(\m (V2 k x) -> IM.insertWith (\_ old -> IS.insert x old) k (IS.singleton x) m)
|
||||||
|
imis
|
||||||
|
|
||||||
|
pairsToIntMapSet :: [V2 Int] -> IM.IntMap IS.IntSet
|
||||||
|
pairsToIntMapSet = foldl'
|
||||||
|
(\m (V2 k x) -> IM.insertWith (\_ old -> IS.insert x old) k (IS.singleton x) m)
|
||||||
|
IM.empty
|
||||||
Reference in New Issue
Block a user