]> gitweb.michael.orlitzky.com - spline3.git/blob - src/Tetrahedron.hs
Fix all orphan instances.
[spline3.git] / src / Tetrahedron.hs
1 module Tetrahedron
2 where
3
4 import Numeric.LinearAlgebra hiding (i, scale)
5 import Prelude hiding (LT)
6 import Test.QuickCheck (Arbitrary(..), Gen)
7
8 import Cardinal
9 import FunctionValues
10 import Misc (factorial)
11 import Point
12 import RealFunction
13 import ThreeDimensional
14
15 data Tetrahedron = Tetrahedron { fv :: FunctionValues,
16 v0 :: Point,
17 v1 :: Point,
18 v2 :: Point,
19 v3 :: Point }
20 deriving (Eq)
21
22
23 instance Arbitrary Tetrahedron where
24 arbitrary = do
25 rnd_v0 <- arbitrary :: Gen Point
26 rnd_v1 <- arbitrary :: Gen Point
27 rnd_v2 <- arbitrary :: Gen Point
28 rnd_v3 <- arbitrary :: Gen Point
29 rnd_fv <- arbitrary :: Gen FunctionValues
30 return (Tetrahedron rnd_fv rnd_v0 rnd_v1 rnd_v2 rnd_v3)
31
32
33 instance Show Tetrahedron where
34 show t = "Tetrahedron:\n" ++
35 " fv: " ++ (show (fv t)) ++ "\n" ++
36 " v0: " ++ (show (v0 t)) ++ "\n" ++
37 " v1: " ++ (show (v1 t)) ++ "\n" ++
38 " v2: " ++ (show (v2 t)) ++ "\n" ++
39 " v3: " ++ (show (v3 t)) ++ "\n"
40
41
42 instance ThreeDimensional Tetrahedron where
43 center t = ((v0 t) + (v1 t) + (v2 t) + (v3 t)) `scale` (1/4)
44 contains_point t p =
45 (b0 t p) >= 0 && (b1 t p) >= 0 && (b2 t p) >= 0 && (b3 t p) >= 0
46
47
48 polynomial :: Tetrahedron -> (RealFunction Point)
49 polynomial t =
50 sum [ (c t i j k l) `cmult` (beta t i j k l) | i <- [0..3],
51 j <- [0..3],
52 k <- [0..3],
53 l <- [0..3],
54 i + j + k + l == 3]
55
56
57 -- | Returns the domain point of t with indices i,j,k,l.
58 -- Simply an alias for the domain_point function.
59 xi :: Tetrahedron -> Int -> Int -> Int -> Int -> Point
60 xi = domain_point
61
62 -- | Returns the domain point of t with indices i,j,k,l.
63 domain_point :: Tetrahedron -> Int -> Int -> Int -> Int -> Point
64 domain_point t i j k l
65 | i + j + k + l == 3 = weighted_sum `scale` (1/3)
66 | otherwise = error "domain point index out of bounds"
67 where
68 v0' = (v0 t) `scale` (fromIntegral i)
69 v1' = (v1 t) `scale` (fromIntegral j)
70 v2' = (v2 t) `scale` (fromIntegral k)
71 v3' = (v3 t) `scale` (fromIntegral l)
72 weighted_sum = v0' + v1' + v2' + v3'
73
74
75 -- | The Bernstein polynomial on t with indices i,j,k,l. Denoted by a
76 -- capital 'B' in the Sorokina/Zeilfelder paper.
77 beta :: Tetrahedron -> Int -> Int -> Int -> Int -> (RealFunction Point)
78 beta t i j k l
79 | (i + j + k + l == 3) =
80 coefficient `cmult` (b0_term * b1_term * b2_term * b3_term)
81 | otherwise = error "basis function index out of bounds"
82 where
83 denominator = (factorial i)*(factorial j)*(factorial k)*(factorial l)
84 coefficient = 6 / (fromIntegral denominator)
85 b0_term = (b0 t) `fexp` i
86 b1_term = (b1 t) `fexp` j
87 b2_term = (b2 t) `fexp` k
88 b3_term = (b3 t) `fexp` l
89
90
91 -- | The coefficient function. c t i j k l returns the coefficient
92 -- c_ijkl with respect to the tetrahedron t. The definition uses
93 -- pattern matching to mimic the definitions given in Sorokina and
94 -- Zeilfelder, pp. 84-86. If incorrect indices are supplied, the
95 -- function will simply error.
96 c :: Tetrahedron -> Int -> Int -> Int -> Int -> Double
97 c t 0 0 3 0 = eval (fv t) $
98 (1/8) * (I + F + L + T + LT + FL + FT + FLT)
99
100 c t 0 0 0 3 = eval (fv t) $
101 (1/8) * (I + F + R + T + RT + FR + FT + FRT)
102
103 c t 0 0 2 1 = eval (fv t) $
104 (5/24)*(I + F + T + FT) +
105 (1/24)*(L + FL + LT + FLT)
106
107 c t 0 0 1 2 = eval (fv t) $
108 (5/24)*(I + F + T + FT) +
109 (1/24)*(R + FR + RT + FRT)
110
111 c t 0 1 2 0 = eval (fv t) $
112 (5/24)*(I + F) +
113 (1/8)*(L + T + FL + FT) +
114 (1/24)*(LT + FLT)
115
116 c t 0 1 0 2 = eval (fv t) $
117 (5/24)*(I + F) +
118 (1/8)*(R + T + FR + FT) +
119 (1/24)*(RT + FRT)
120
121 c t 0 1 1 1 = eval (fv t) $
122 (13/48)*(I + F) +
123 (7/48)*(T + FT) +
124 (1/32)*(L + R + FL + FR) +
125 (1/96)*(LT + RT + FLT + FRT)
126
127 c t 0 2 1 0 = eval (fv t) $
128 (13/48)*(I + F) +
129 (17/192)*(L + T + FL + FT) +
130 (1/96)*(LT + FLT) +
131 (1/64)*(R + D + FR + FD) +
132 (1/192)*(RT + LD + FRT + FLD)
133
134 c t 0 2 0 1 = eval (fv t) $
135 (13/48)*(I + F) +
136 (17/192)*(R + T + FR + FT) +
137 (1/96)*(RT + FRT) +
138 (1/64)*(L + D + FL + FD) +
139 (1/192)*(RD + LT + FLT + FRD)
140
141 c t 0 3 0 0 = eval (fv t) $
142 (13/48)*(I + F) +
143 (5/96)*(L + R + T + D + FL + FR + FT + FD) +
144 (1/192)*(RT + RD + LT + LD + FRT + FRD + FLT + FLD)
145
146 c t 1 0 2 0 = eval (fv t) $
147 (1/4)*I +
148 (1/6)*(F + L + T) +
149 (1/12)*(LT + FL + FT)
150
151 c t 1 0 0 2 = eval (fv t) $
152 (1/4)*I +
153 (1/6)*(F + R + T) +
154 (1/12)*(RT + FR + FT)
155
156 c t 1 0 1 1 = eval (fv t) $
157 (1/3)*I +
158 (5/24)*(F + T) +
159 (1/12)*FT +
160 (1/24)*(L + R) +
161 (1/48)*(LT + RT + FL + FR)
162
163 c t 1 1 1 0 = eval (fv t) $
164 (1/3)*I +
165 (5/24)*F +
166 (1/8)*(L + T) +
167 (5/96)*(FL + FT) +
168 (1/48)*(D + R + LT) +
169 (1/96)*(FD + LD + RT + FR)
170
171 c t 1 1 0 1 = eval (fv t) $
172 (1/3)*I +
173 (5/24)*F +
174 (1/8)*(R + T) +
175 (5/96)*(FR + FT) +
176 (1/48)*(D + L + RT) +
177 (1/96)*(FD + LT + RD + FL)
178
179 c t 1 2 0 0 = eval (fv t) $
180 (1/3)*I +
181 (5/24)*F +
182 (7/96)*(L + R + T + D) +
183 (1/32)*(FL + FR + FT + FD) +
184 (1/96)*(RT + RD + LT + LD)
185
186 c t 2 0 1 0 = eval (fv t) $
187 (3/8)*I +
188 (7/48)*(F + T + L) +
189 (1/48)*(R + D + B + LT + FL + FT) +
190 (1/96)*(RT + BT + FR + FD + LD + BL)
191
192 c t 2 0 0 1 = eval (fv t) $
193 (3/8)*I +
194 (7/48)*(F + T + R) +
195 (1/48)*(L + D + B + RT + FR + FT) +
196 (1/96)*(LT + BT + FL + FD + RD + BR)
197
198 c t 2 1 0 0 = eval (fv t) $
199 (3/8)*I +
200 (1/12)*(T + R + L + D) +
201 (1/64)*(FT + FR + FL + FD) +
202 (7/48)*F +
203 (1/48)*B +
204 (1/96)*(RT + LD + LT + RD) +
205 (1/192)*(BT + BR + BL + BD)
206
207 c t 3 0 0 0 = eval (fv t) $
208 (3/8)*I +
209 (1/12)*(T + F + L + R + D + B) +
210 (1/96)*(LT + FL + FT + RT + BT + FR) +
211 (1/96)*(FD + LD + BD + BR + RD + BL)
212
213 c _ _ _ _ _ = error "coefficient index out of bounds"
214
215
216
217 -- | The matrix used in the tetrahedron volume calculation as given in
218 -- Lai & Schumaker, Definition 15.4, page 436.
219 vol_matrix :: Tetrahedron -> Matrix Double
220 vol_matrix t = (4><4)
221 [1, 1, 1, 1,
222 x1, x2, x3, x4,
223 y1, y2, y3, y4,
224 z1, z2, z3, z4 ]
225 where
226 x1 = x_coord (v0 t)
227 x2 = x_coord (v1 t)
228 x3 = x_coord (v2 t)
229 x4 = x_coord (v3 t)
230 y1 = y_coord (v0 t)
231 y2 = y_coord (v1 t)
232 y3 = y_coord (v2 t)
233 y4 = y_coord (v3 t)
234 z1 = z_coord (v0 t)
235 z2 = z_coord (v1 t)
236 z3 = z_coord (v2 t)
237 z4 = z_coord (v3 t)
238
239 -- | Computed using the formula from Lai & Schumaker, Definition 15.4,
240 -- page 436.
241 volume :: Tetrahedron -> Double
242 volume t
243 | (v0 t) == (v1 t) = 0
244 | (v0 t) == (v2 t) = 0
245 | (v0 t) == (v3 t) = 0
246 | (v1 t) == (v2 t) = 0
247 | (v1 t) == (v3 t) = 0
248 | (v2 t) == (v3 t) = 0
249 | otherwise = (1/6)*(det (vol_matrix t))
250
251
252 -- | The barycentric coordinates of a point with respect to v0.
253 b0 :: Tetrahedron -> (RealFunction Point)
254 b0 t point = (volume inner_tetrahedron) / (volume t)
255 where
256 inner_tetrahedron = t { v0 = point }
257
258
259 -- | The barycentric coordinates of a point with respect to v1.
260 b1 :: Tetrahedron -> (RealFunction Point)
261 b1 t point = (volume inner_tetrahedron) / (volume t)
262 where
263 inner_tetrahedron = t { v1 = point }
264
265
266 -- | The barycentric coordinates of a point with respect to v2.
267 b2 :: Tetrahedron -> (RealFunction Point)
268 b2 t point = (volume inner_tetrahedron) / (volume t)
269 where
270 inner_tetrahedron = t { v2 = point }
271
272
273 -- | The barycentric coordinates of a point with respect to v3.
274 b3 :: Tetrahedron -> (RealFunction Point)
275 b3 t point = (volume inner_tetrahedron) / (volume t)
276 where
277 inner_tetrahedron = t { v3 = point }