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)
{-# INLINE collidePoint #-}
collidePoint sp ep = foldl' findPoint (ep, Nothing)
collidePoint sp ep = foldl' f (ep, Nothing)
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)]
{-# INLINE overlapSegCrs #-}
overlapSegCrs sp ep =
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)
{-# INLINE doBounce #-}
@@ -126,10 +127,9 @@ collide3 sp ep w =
-- Just (hitpoint,normaltosurface)
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
f x wl = collide3Wall sp wl x
wls = wlsNearSeg (xyV3 sp) (xyV3 ep) w
collide3Floors ::
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
where
f wl = case uncurry (intersectCircSeg p r) $ _wlLine wl of
[] -> mempty
xs -> (xs, S.singleton (wl ^. wlLine))
(Nothing,Nothing) -> mempty
(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
| otherwise =
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
$ w ^. cWorld . lWorld . pulseBalls
+20 -13
View File
@@ -7,7 +7,6 @@ module Geometry.Intersect where
import Control.Applicative
import Control.Lens
import Control.Monad
import Data.List
import Data.Maybe
import Geometry.Data
import Geometry.LHS
@@ -348,18 +347,26 @@ inSegArea a b c = param >= 0 && param <= dotV (b -.- a) (b -.- a)
where
param = dotV (b -.- a) (c -.- a)
-- I suspect that this may not be correct...
-- it should probably use closestPointOnSeg
intersectCircSeg :: Point2 -> Float -> Point2 -> Point2 -> [Point2]
intersectCircSeg c r a b
| y < 0 = []
| otherwise = nub $ filter (inSegArea a b) [d -.- v, d +.+ v]
intersectCircSeg :: Point2 -> Float -> Point2 -> Point2 -> (Maybe Point2,Maybe Point2)
intersectCircSeg c r s e = intersectCircLineAlong c r s e
& g
& each %~ f
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)
f (Just x) | x >= 0 && x < 1 = Just $ s + x *^ (e - s)
f _ = Nothing
g Nothing = (Nothing,Nothing)
g (Just (x,y)) = (Just x,Just y)
--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 p r x y = do
@@ -415,4 +422,4 @@ intersectCircSegTest c r x y =
z = r *.* vNormal (normalizeV x - y)
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