2014-04-22 03:00:39 +02:00
|
|
|
module Map.Map where
|
2014-04-18 16:07:51 +02:00
|
|
|
|
|
|
|
import Map.Types
|
|
|
|
|
2014-05-15 10:44:54 +02:00
|
|
|
import Data.Array (bounds, (!))
|
2014-05-16 17:26:40 +02:00
|
|
|
import Data.List (sort, group)
|
2014-04-24 02:45:55 +02:00
|
|
|
|
|
|
|
-- WARNING: Does NOT Check for neighbours exceeding maximum map coordinates yet.
|
|
|
|
unsafeGiveNeighbours :: (Int, Int) -- ^ original coordinates
|
|
|
|
-> [(Int,Int)] -- ^ list of neighbours
|
|
|
|
unsafeGiveNeighbours (x,z) = filter (not . negative) allNs
|
2014-04-18 16:07:51 +02:00
|
|
|
where
|
2014-04-24 02:45:55 +02:00
|
|
|
allNs = if even z then [(x+1,z), (x-1,z), (x,z+1), (x,z-1), (x+1,z+1), (x+1,z-1)]
|
|
|
|
else [(x+1,z), (x-1,z), (x,z+1), (x,z-1), (x-1,z+1), (x-1,z-1)]
|
2014-04-18 16:07:51 +02:00
|
|
|
|
|
|
|
negative :: (Int, Int) -> Bool
|
2014-04-24 02:45:55 +02:00
|
|
|
negative (a,b) = a < 0 || b < 0
|
|
|
|
|
|
|
|
giveNeighbours :: PlayMap -- ^ Map on which to find neighbours
|
|
|
|
-> (Int, Int) -- ^ original coordinates
|
|
|
|
-> [(Int, Int)] -- ^ list of neighbours
|
|
|
|
giveNeighbours mp (x,z) = filter (not . outOfBounds mp) allNs
|
|
|
|
where
|
|
|
|
allNs = if even z then [(x+1,z), (x-1,z), (x,z+1), (x,z-1), (x+1,z+1), (x+1,z-1)]
|
|
|
|
else [(x+1,z), (x-1,z), (x,z+1), (x,z-1), (x-1,z+1), (x-1,z-1)]
|
|
|
|
|
|
|
|
outOfBounds :: PlayMap -> (Int, Int) -> Bool
|
|
|
|
outOfBounds mp' (a,b) = let (lo,hi) = bounds mp' in
|
|
|
|
a < fst lo || b < snd lo || a > fst hi || b > snd hi
|
|
|
|
|
|
|
|
giveNeighbourhood :: PlayMap -- ^ map on which to find neighbourhood
|
|
|
|
-> Int -- ^ iterative
|
|
|
|
-> (Int, Int) -- ^ original coordinates
|
|
|
|
-> [(Int, Int)] -- ^ neighbourhood
|
|
|
|
giveNeighbourhood _ 0 (a,b) = [(a,b)]
|
|
|
|
giveNeighbourhood mp n (a,b) = let ns = giveNeighbours mp (a,b) in
|
2014-04-25 15:58:25 +02:00
|
|
|
remdups . concat $ ns : map (giveNeighbourhood mp (n-1)) ns
|
2014-04-24 02:45:55 +02:00
|
|
|
|
2014-05-15 10:44:54 +02:00
|
|
|
-- | Calculates the height of any given point on the map.
|
2014-05-16 17:26:40 +02:00
|
|
|
-- Does not add camera distance to ground to that.
|
2014-05-15 10:44:54 +02:00
|
|
|
giveMapHeight :: PlayMap
|
2014-05-16 17:26:40 +02:00
|
|
|
-> (Double, Double)
|
|
|
|
-> Double
|
2014-05-17 11:40:23 +02:00
|
|
|
giveMapHeight mop (x, z)
|
2014-05-16 18:59:26 +02:00
|
|
|
| outsideMap (x,z') = 0.0
|
|
|
|
| otherwise = sum $ map (\(p,d) -> (hlu p) * (1 - (d / totald))) tups
|
2014-05-15 10:44:54 +02:00
|
|
|
where
|
2014-05-17 11:40:23 +02:00
|
|
|
z' = z * 2/(sqrt 3)
|
2014-05-16 18:59:26 +02:00
|
|
|
|
2014-05-16 17:26:40 +02:00
|
|
|
outsideMap :: (Double, Double) -> Bool
|
|
|
|
outsideMap (mx, mz) = let ((a,b),(c,d)) = bounds mop
|
2014-05-16 11:30:15 +02:00
|
|
|
fr = fromIntegral
|
|
|
|
in mx < (fr a) || mx > (fr c) || mz < (fr b) || mz > (fr d)
|
2014-05-16 18:48:46 +02:00
|
|
|
|
2014-05-16 17:26:40 +02:00
|
|
|
-- Height LookUp on PlayMap
|
|
|
|
hlu :: (Int, Int) -> Double
|
|
|
|
hlu (k,j) = let (Node _ (_,_,y) _ _ _ _ _ _) = mop ! (k,j) in y
|
2014-05-15 10:44:54 +02:00
|
|
|
|
2014-05-16 17:26:40 +02:00
|
|
|
-- reference Points
|
2014-05-16 17:56:03 +02:00
|
|
|
refs :: [(Int, Int)]
|
2014-05-16 18:59:26 +02:00
|
|
|
refs = remdups $ map clmp $ map (tadd (floor x, floor z')) mods
|
2014-05-16 17:56:03 +02:00
|
|
|
where
|
2014-05-16 18:48:46 +02:00
|
|
|
mods = [(-1,-1),(-1,2),(0,0),(0,1),(1,0),(1,1),(2,-1),(2,2)]
|
2014-05-16 17:56:03 +02:00
|
|
|
tadd (a,b) (c,d) = (a+b,c+d)
|
2014-05-15 10:44:54 +02:00
|
|
|
|
2014-05-16 17:26:40 +02:00
|
|
|
-- tupels with reference point and distance
|
2014-05-16 18:59:26 +02:00
|
|
|
tups = map (\t -> (t, dist (x,z') t)) refs
|
2014-05-15 10:44:54 +02:00
|
|
|
|
2014-05-16 17:26:40 +02:00
|
|
|
-- total distance of all for reference point from the point in question
|
|
|
|
totald = sum $ map (\(_,d) -> d) tups
|
2014-05-15 10:44:54 +02:00
|
|
|
|
2014-05-16 18:48:46 +02:00
|
|
|
-- clamp, as she is programmed
|
|
|
|
clamp :: (Ord a) => a -> a -> a -> a
|
|
|
|
clamp mn mx = max mn . min mx
|
|
|
|
|
|
|
|
-- clamp for tupels
|
|
|
|
clmp :: (Int, Int) -> (Int, Int)
|
|
|
|
clmp (a,b) = let ((xmin,zmin),(xmax,zmax)) = bounds mop
|
|
|
|
in ((clamp (xmin+2) (xmax-2) a),(clamp (zmin+2) (zmax-2) b))
|
|
|
|
|
2014-05-16 17:26:40 +02:00
|
|
|
-- Real distance on PlayMap
|
|
|
|
dist :: (Double, Double) -> (Int, Int) -> Double
|
|
|
|
dist (x1,z1) pmp = let xf = x1 - realx
|
|
|
|
zf = z1 - realz
|
|
|
|
in sqrt $ xf*xf + zf*zf
|
|
|
|
where
|
|
|
|
realx = (\(Node _ (nx,_,_) _ _ _ _ _ _) -> nx) (mop ! pmp)
|
|
|
|
realz = (\(Node _ (_,nz,_) _ _ _ _ _ _) -> nz) (mop ! pmp)
|
2014-05-15 10:44:54 +02:00
|
|
|
|
2014-04-24 02:45:55 +02:00
|
|
|
-- removing duplicates in O(n log n), losing order and adding Ord requirement
|
|
|
|
remdups :: Ord a => [a] -> [a]
|
|
|
|
remdups = map head . group . sort
|