1 -- Copyright (c) 2000 Galois Connections, Inc.
2 -- All rights reserved. This software is distributed as
3 -- free software under the license in the file "LICENSE",
4 -- which is included in the distribution.
9 , emptyIList, openIList
11 , entryexit, exitentry
13 , unionIntervals, intersectIntervals, differenceIntervals
19 -- The result of a ray trace is represented as a list of surface
20 -- intersections. Each intersection is a point along the ray with
21 -- a flag indicating whether this intersection is an entry or an
22 -- exit from the solid. Each intersection also carries unspecified
23 -- surface data for use by the illumination model.
25 -- Just the list of intersections isn't enough, however. An empty
26 -- list can denote either a trace that is always within the solid
27 -- or never in the solid. To dissambiguate, an extra flag is kept
28 -- that indicates whether we are starting inside or outside of the
29 -- solid. As a convenience, we also keep an additional flag that
30 -- indicates whether the last intersection ends inside or outside.
32 type IList a = (Bool, [Intersection a], Bool)
33 type Intersection a = (Double, Bool, a)
35 emptyIList = (False, [], False)
36 openIList = (True, [], True)
38 mapI f (b1, is, b2) = (b1, map f is, b2)
40 isEntry (_, entry, _) = entry
41 isExit (_, entry, _) = not entry
43 mkEntry (t, a) = (t, True, a)
44 mkExit (t, a) = (t, False, a)
46 entryexit w1 w2 = (False, [mkEntry w1, mkExit w2], False)
47 exitentry w1 w2 = (True, [mkExit w1, mkEntry w2], True)
48 arrange w1@(t1, _) w2@(t2, _) | t1 < t2 = entryexit w1 w2
49 | otherwise = entryexit w2 w1
52 cmpI :: Intersection a -> Intersection a -> Ordering
53 cmpI (i, _, _) (j, _, _)
58 bad (b1, [], b2) = b1 /= b2
59 bad (b1, is, b2) = bad' b1 is || b2 /= b3
60 where (_, b3, _) = last is
63 bad' b ((_, c, _) : is) = b == c || bad' c is
65 unionIntervals :: IList a -> IList a -> IList a
66 unionIntervals (isStartOpen, is, isEndOpen) (jsStartOpen, js, jsEndOpen)
67 = (isStartOpen || jsStartOpen, uniIntervals is js, isEndOpen || jsEndOpen)
68 where uniIntervals is [] | jsEndOpen = []
70 uniIntervals [] js | isEndOpen = []
72 uniIntervals is@(i : is') js@(j : js')
74 EQ -> if isEntry i == isEntry j then i : uniIntervals is' js'
75 else uniIntervals is' js'
76 LT -> if isEntry j then i : uniIntervals is' js
77 else uniIntervals is' js
78 GT -> if isEntry i then j : uniIntervals is js'
79 else uniIntervals is js'
81 intersectIntervals :: IList a -> IList a -> IList a
82 intersectIntervals is js
83 = complementIntervals (unionIntervals is' js')
84 where is' = complementIntervals is
85 js' = complementIntervals js
87 differenceIntervals :: IList a -> IList a -> IList a
88 differenceIntervals is js
89 = complementIntervals (unionIntervals is' js)
90 where is' = complementIntervals is
92 complementIntervals :: IList a -> IList a
93 complementIntervals (o1, is, o2)
94 = (not o1, [ (i, not isentry, a) | (i, isentry, a) <- is ], not o2)
99 mkIn, mkOut :: Double -> Intersection a
100 mkIn x = (x, True, undefined)
101 mkOut x = (x, False, undefined)
103 i1 = (False, [ mkIn 2, mkOut 7 ], False)
104 i1' = (True, [ mkOut 2, mkIn 7 ], True)
105 i2 = (False, [ mkIn 1, mkOut 3, mkIn 4, mkOut 5, mkIn 6, mkOut 8 ], False)
107 t1 = unionIntervals i1 i2
108 t2 = intersectIntervals i1 i2
109 t3 = intersectIntervals i2 i1
110 t4 = complementIntervals i1
111 t5 = intersectIntervals i2 i1'
112 t6 = differenceIntervals i2 i1
113 t7 = differenceIntervals i2 i2
116 do if o1 then putStr "..." else return ()
117 putStr $ foldr1 (++) (map si is)
118 if o2 then putStr "..." else return ()
119 si (i, True, _, _) = "<" ++ show i
120 si (i, False, _, _) = " " ++ show i ++ ">"