Clarify circle segment intersection

This commit is contained in:
2025-10-11 11:13:35 +01:00
parent 49fb982877
commit 4949d98789
4 changed files with 28 additions and 21 deletions
+5 -5
View File
@@ -53,15 +53,16 @@ import Geometry
collidePoint :: Point2 -> Point2 -> [Wall] -> (Point2, Maybe Wall) collidePoint :: Point2 -> Point2 -> [Wall] -> (Point2, Maybe Wall)
{-# INLINE collidePoint #-} {-# INLINE collidePoint #-}
collidePoint sp ep = foldl' findPoint (ep, Nothing) collidePoint sp ep = foldl' f (ep, Nothing)
where where
findPoint (p, mwl) wl = maybe (p, mwl) (,Just wl) . uncurry (intersectSegSeg sp p) . _wlLine $ wl f (p, mwl) wl
= maybe (p, mwl) (,Just wl) . uncurry (intersectSegSeg sp p) . _wlLine $ wl
overlapSegCrs :: Point2 -> Point2 -> [Creature] -> [(Point2, Creature)] overlapSegCrs :: Point2 -> Point2 -> [Creature] -> [(Point2, Creature)]
{-# INLINE overlapSegCrs #-} {-# INLINE overlapSegCrs #-}
overlapSegCrs sp ep = overlapSegCrs sp ep =
mapMaybe mapMaybe
(\cr -> (,cr) <$> listToMaybe (intersectCircSeg (cr ^. crPos . _xy) (crRad $ cr ^. crType) sp ep)) (\cr -> (,cr) <$> fst (intersectCircSeg (cr ^. crPos . _xy) (crRad $ cr ^. crType) sp ep))
doBounce :: Float -> Point2 -> Point2 -> (Point2, Maybe Wall) -> Maybe (Point2, Point2) doBounce :: Float -> Point2 -> Point2 -> (Point2, Maybe Wall) -> Maybe (Point2, Point2)
{-# INLINE doBounce #-} {-# INLINE doBounce #-}
@@ -126,10 +127,9 @@ collide3 sp ep w =
-- Just (hitpoint,normaltosurface) -- Just (hitpoint,normaltosurface)
collide3Walls :: Point3 -> World -> (Point3, MPO) -> (Point3, MPO) collide3Walls :: Point3 -> World -> (Point3, MPO) -> (Point3, MPO)
collide3Walls sp w e@(ep, _) = foldl' f e wls collide3Walls sp w e@(ep, _) = foldl' f e $ wlsNearSeg (xyV3 sp) (xyV3 ep) w
where where
f x wl = collide3Wall sp wl x f x wl = collide3Wall sp wl x
wls = wlsNearSeg (xyV3 sp) (xyV3 ep) w
collide3Floors :: collide3Floors ::
Point3 -> Point3 ->
+2 -2
View File
@@ -100,5 +100,5 @@ wallBlips :: Point2 -> Float -> World -> ([Point2], S.Set (Point2, Point2))
wallBlips p r = foldMap f . wlsNearCirc p r wallBlips p r = foldMap f . wlsNearCirc p r
where where
f wl = case uncurry (intersectCircSeg p r) $ _wlLine wl of f wl = case uncurry (intersectCircSeg p r) $ _wlLine wl of
[] -> mempty (Nothing,Nothing) -> mempty
xs -> (xs, S.singleton (wl ^. wlLine)) (a,b) -> (maybeToList a <> maybeToList b, S.singleton (wl ^. wlLine))
+1 -1
View File
@@ -91,7 +91,7 @@ pbsHit sp ep w
| sp == ep = mempty | sp == ep = mempty
| otherwise = | otherwise =
sortOn (dist sp . fst) sortOn (dist sp . fst)
. mapMaybe (\pb -> (,pb) <$> listToMaybe (intersectCircSeg (_pbPos pb) 8 sp ep)) . mapMaybe (\pb -> (,pb) <$> fst (intersectCircSeg (_pbPos pb) 8 sp ep))
. IM.elems . IM.elems
$ w ^. cWorld . lWorld . pulseBalls $ w ^. cWorld . lWorld . pulseBalls
+20 -13
View File
@@ -7,7 +7,6 @@ module Geometry.Intersect where
import Control.Applicative import Control.Applicative
import Control.Lens import Control.Lens
import Control.Monad import Control.Monad
import Data.List
import Data.Maybe import Data.Maybe
import Geometry.Data import Geometry.Data
import Geometry.LHS import Geometry.LHS
@@ -348,18 +347,26 @@ inSegArea a b c = param >= 0 && param <= dotV (b -.- a) (b -.- a)
where where
param = dotV (b -.- a) (c -.- a) param = dotV (b -.- a) (c -.- a)
-- I suspect that this may not be correct... intersectCircSeg :: Point2 -> Float -> Point2 -> Point2 -> (Maybe Point2,Maybe Point2)
-- it should probably use closestPointOnSeg intersectCircSeg c r s e = intersectCircLineAlong c r s e
intersectCircSeg :: Point2 -> Float -> Point2 -> Point2 -> [Point2] & g
intersectCircSeg c r a b & each %~ f
| y < 0 = []
| otherwise = nub $ filter (inSegArea a b) [d -.- v, d +.+ v]
where where
d = closestPointOnLine a b c f (Just x) | x >= 0 && x < 1 = Just $ s + x *^ (e - s)
x = dist d c f _ = Nothing
y = r ^ (2 :: Int) - x ^ (2 :: Int) g Nothing = (Nothing,Nothing)
z = sqrt y g (Just (x,y)) = (Just x,Just y)
v = z *.* normalizeV (b -.- a)
--intersectCircSeg :: Point2 -> Float -> Point2 -> Point2 -> [Point2]
--intersectCircSeg c r a b
-- | y < 0 = []
-- | otherwise = nub $ filter (inSegArea a b) [d -.- v, d +.+ v]
-- where
-- d = closestPointOnLine a b c
-- x = dist d c
-- y = r ^ (2 :: Int) - x ^ (2 :: Int)
-- z = sqrt y
-- v = z *.* normalizeV (b -.- a)
intersectCircLineAlong :: Point2 -> Float -> Point2 -> Point2 -> Maybe (Float, Float) intersectCircLineAlong :: Point2 -> Float -> Point2 -> Point2 -> Maybe (Float, Float)
intersectCircLineAlong p r x y = do intersectCircLineAlong p r x y = do
@@ -415,4 +422,4 @@ intersectCircSegTest c r x y =
z = r *.* vNormal (normalizeV x - y) z = r *.* vNormal (normalizeV x - y)
intersectCircSegFirst :: Point2 -> Float -> Point2 -> Point2 -> Maybe Point2 intersectCircSegFirst :: Point2 -> Float -> Point2 -> Point2 -> Maybe Point2
intersectCircSegFirst c r a = listToMaybe . intersectCircSeg c r a intersectCircSegFirst c r a = fst . intersectCircSeg c r a