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