]> gitweb.michael.orlitzky.com - spline3.git/blob - src/Tests/Face.hs
Add some HUnit tests for the Face module.
[spline3.git] / src / Tests / Face.hs
1 module Tests.Face
2 where
3
4 import Control.Monad (unless)
5 import Test.HUnit
6 import Test.QuickCheck
7
8 import Comparisons
9 import Cube (Cube(grid), cube_at, top)
10 import Face (face0,
11 face2,
12 face5,
13 tetrahedron0,
14 tetrahedron1,
15 tetrahedron2,
16 tetrahedron3,
17 tetrahedrons)
18 import Grid (Grid(h), make_grid)
19 import Tetrahedron
20
21
22 -- HUnit tests.
23
24 -- | An HUnit assertion that wraps the almost_equals function. Stolen
25 -- from the definition of assertEqual in Test/HUnit/Base.hs.
26 assertAlmostEqual :: String -> Double -> Double -> Assertion
27 assertAlmostEqual preface expected actual =
28 unless (actual ~= expected) (assertFailure msg)
29 where msg = (if null preface then "" else preface ++ "\n") ++
30 "expected: " ++ show expected ++ "\n but got: " ++ show actual
31
32
33 -- | Values of the function f(x,y,z) = 1 + x + xy + xyz taken at nine
34 -- points (hi, hj, jk) with h = 1. From example one in the paper.
35 -- Used in the next bunch of tests.
36 trilinear :: [[[Double]]]
37 trilinear = [ [ [ 1, 2, 3 ],
38 [ 1, 3, 5 ],
39 [ 1, 4, 7 ] ],
40 [ [ 1, 2, 3 ],
41 [ 1, 4, 7 ],
42 [ 1, 6, 11 ] ],
43 [ [ 1, 2, 3 ],
44 [ 1, 5, 9 ],
45 [ 1, 8, 15 ]]]
46
47 -- | Check the value of c0030 for any tetrahedron belonging to the
48 -- cube centered on (1,1,1) with a grid constructed from the
49 -- trilinear values. See example one in the paper.
50 test_trilinear_c0030 :: Test
51 test_trilinear_c0030 =
52 TestCase $ assertAlmostEqual "c0030 is correct" (c t 0 0 3 0) (17/8)
53 where
54 g = make_grid 1 trilinear
55 cube = cube_at g 1 1 1
56 t = head (tetrahedrons cube) -- Any one will do.
57
58
59 -- | Check the value of c0003 for any tetrahedron belonging to the
60 -- cube centered on (1,1,1) with a grid constructed from the
61 -- trilinear values. See example one in the paper.
62 test_trilinear_c0003 :: Test
63 test_trilinear_c0003 =
64 TestCase $ assertAlmostEqual "c0003 is correct" (c t 0 0 0 3) (27/8)
65 where
66 g = make_grid 1 trilinear
67 cube = cube_at g 1 1 1
68 t = head (tetrahedrons cube) -- Any one will do.
69
70
71 -- | Check the value of c0021 for any tetrahedron belonging to the
72 -- cube centered on (1,1,1) with a grid constructed from the
73 -- trilinear values. See example one in the paper.
74 test_trilinear_c0021 :: Test
75 test_trilinear_c0021 =
76 TestCase $ assertAlmostEqual "c0021 is correct" (c t 0 0 2 1) (61/24)
77 where
78 g = make_grid 1 trilinear
79 cube = cube_at g 1 1 1
80 t = head (tetrahedrons cube) -- Any one will do.
81
82
83 -- | Check the value of c0012 for any tetrahedron belonging to the
84 -- cube centered on (1,1,1) with a grid constructed from the
85 -- trilinear values. See example one in the paper.
86 test_trilinear_c0012 :: Test
87 test_trilinear_c0012 =
88 TestCase $ assertAlmostEqual "c0012 is correct" (c t 0 0 1 2) (71/24)
89 where
90 g = make_grid 1 trilinear
91 cube = cube_at g 1 1 1
92 t = head (tetrahedrons cube) -- Any one will do.
93
94
95 -- | Check the value of c0120 for any tetrahedron belonging to the
96 -- cube centered on (1,1,1) with a grid constructed from the
97 -- trilinear values. See example one in the paper.
98 test_trilinear_c0120 :: Test
99 test_trilinear_c0120 =
100 TestCase $ assertAlmostEqual "c0120 is correct" (c t 0 1 2 0) (55/24)
101 where
102 g = make_grid 1 trilinear
103 cube = cube_at g 1 1 1
104 t = head (tetrahedrons cube) -- Any one will do.
105
106
107 face_tests :: [Test]
108 face_tests = [test_trilinear_c0030,
109 test_trilinear_c0003,
110 test_trilinear_c0021,
111 test_trilinear_c0012,
112 test_trilinear_c0120]
113
114
115 -- QuickCheck Tests.
116
117 -- | Since the grid size is necessarily positive, all tetrahedrons
118 -- (which comprise cubes of positive volume) must have positive volume
119 -- as well.
120 prop_all_volumes_positive :: Cube -> Property
121 prop_all_volumes_positive c =
122 (delta > 0) ==> (null nonpositive_volumes)
123 where
124 delta = h (grid c)
125 ts = tetrahedrons c
126 volumes = map volume ts
127 nonpositive_volumes = filter (<= 0) volumes
128
129
130 -- | Given in Sorokina and Zeilfelder, p. 78.
131 prop_cijk1_identity :: Cube -> Bool
132 prop_cijk1_identity cube =
133 and [ c t0' i j k 1 ~= (c t1' (i+1) j k 0) * ((b0 t0') (v3 t1')) +
134 (c t1' i (j+1) k 0) * ((b1 t0') (v3 t1')) +
135 (c t1' i j (k+1) 0) * ((b2 t0') (v3 t1')) +
136 (c t1' i j k 1) * ((b3 t0') (v3 t1')) | i <- [0..2],
137 j <- [0..2],
138 k <- [0..2],
139 i + j + k == 2]
140 where
141 t0 = tetrahedron0 (face0 cube)
142 t1 = tetrahedron1 (face0 cube)
143 t0' = Tetrahedron cube (v3 t0) (v2 t0) (v1 t0) (v0 t0)
144 t1' = Tetrahedron cube (v3 t1) (v2 t1) (v0 t1) (v1 t1)
145
146 -- | Given in Sorokina and Zeilfelder, p. 79.
147 prop_c0120_identity1 :: Cube -> Bool
148 prop_c0120_identity1 cube =
149 c t0' 0 1 2 0 ~= (c t0' 0 0 2 1 + c t1' 0 0 2 1) / 2
150 where
151 t0 = tetrahedron0 (face0 cube)
152 t1 = tetrahedron1 (face0 cube)
153 t0' = Tetrahedron cube (v3 t0) (v2 t0) (v1 t0) (v0 t0)
154 t1' = Tetrahedron cube (v3 t1) (v2 t1) (v0 t1) (v1 t1)
155
156
157 -- | Given in Sorokina and Zeilfelder, p. 79.
158 prop_c0210_identity1 :: Cube -> Bool
159 prop_c0210_identity1 cube =
160 c t0' 0 2 1 0 ~= (c t0' 0 1 1 1 + c t1' 0 1 1 1) / 2
161 where
162 t0 = tetrahedron0 (face0 cube)
163 t1 = tetrahedron1 (face0 cube)
164 t0' = Tetrahedron cube (v3 t0) (v2 t0) (v1 t0) (v0 t0)
165 t1' = Tetrahedron cube (v3 t1) (v2 t1) (v0 t1) (v1 t1)
166
167
168 -- | Given in Sorokina and Zeilfelder, p. 79.
169 prop_c0300_identity1 :: Cube -> Bool
170 prop_c0300_identity1 cube =
171 c t0' 0 3 0 0 ~= (c t0' 0 2 0 1 + c t1' 0 2 0 1) / 2
172 where
173 t0 = tetrahedron0 (face0 cube)
174 t1 = tetrahedron1 (face0 cube)
175 t0' = Tetrahedron cube (v3 t0) (v2 t0) (v1 t0) (v0 t0)
176 t1' = Tetrahedron cube (v3 t1) (v2 t1) (v0 t1) (v1 t1)
177
178 -- | Given in Sorokina and Zeilfelder, p. 79.
179 prop_c1110_identity :: Cube -> Bool
180 prop_c1110_identity cube =
181 c t0' 1 1 1 0 ~= (c t0' 1 0 1 1 + c t1' 1 0 1 1) / 2
182 where
183 t0 = tetrahedron0 (face0 cube)
184 t1 = tetrahedron1 (face0 cube)
185 t0' = Tetrahedron cube (v3 t0) (v2 t0) (v1 t0) (v0 t0)
186 t1' = Tetrahedron cube (v3 t1) (v2 t1) (v0 t1) (v1 t1)
187
188
189 -- | Given in Sorokina and Zeilfelder, p. 79.
190 prop_c1200_identity1 :: Cube -> Bool
191 prop_c1200_identity1 cube =
192 c t0' 1 2 0 0 ~= (c t0' 1 1 0 1 + c t1' 1 1 0 1) / 2
193 where
194 t0 = tetrahedron0 (face0 cube)
195 t1 = tetrahedron1 (face0 cube)
196 t0' = Tetrahedron cube (v3 t0) (v2 t0) (v1 t0) (v0 t0)
197 t1' = Tetrahedron cube (v3 t1) (v2 t1) (v0 t1) (v1 t1)
198
199
200 -- | Given in Sorokina and Zeilfelder, p. 79.
201 prop_c2100_identity1 :: Cube -> Bool
202 prop_c2100_identity1 cube =
203 c t0' 2 1 0 0 ~= (c t0' 2 0 0 1 + c t1' 2 0 0 1) / 2
204 where
205 t0 = tetrahedron0 (face0 cube)
206 t1 = tetrahedron1 (face0 cube)
207 t0' = Tetrahedron cube (v3 t0) (v2 t0) (v1 t0) (v0 t0)
208 t1' = Tetrahedron cube (v3 t1) (v2 t1) (v0 t1) (v1 t1)
209
210
211 -- | Given in Sorokina and Zeilfelder, p. 79.
212 prop_c0102_identity1 :: Cube -> Bool
213 prop_c0102_identity1 cube =
214 c t0' 0 1 0 2 ~= (c t0' 0 0 1 2 + c t3' 0 0 1 2) / 2
215 where
216 t0 = tetrahedron0 (face0 cube)
217 t3 = tetrahedron3 (face0 cube)
218 t0' = Tetrahedron cube (v3 t0) (v2 t0) (v1 t0) (v0 t0)
219 t3' = Tetrahedron cube (v3 t3) (v2 t3) (v1 t3) (v0 t3)
220
221
222 -- | Given in Sorokina and Zeilfelder, p. 79.
223 prop_c0201_identity1 :: Cube -> Bool
224 prop_c0201_identity1 cube =
225 c t0' 0 2 0 1 ~= (c t0' 0 1 1 1 + c t3' 0 1 1 1) / 2
226 where
227 t0 = tetrahedron0 (face0 cube)
228 t3 = tetrahedron3 (face0 cube)
229 t0' = Tetrahedron cube (v3 t0) (v2 t0) (v1 t0) (v0 t0)
230 t3' = Tetrahedron cube (v3 t3) (v2 t3) (v1 t3) (v0 t3)
231
232
233 -- | Given in Sorokina and Zeilfelder, p. 79.
234 prop_c0300_identity2 :: Cube -> Bool
235 prop_c0300_identity2 cube =
236 c t0' 3 0 0 0 ~= (c t0' 0 2 1 0 + c t3' 0 2 1 0) / 2
237 where
238 t0 = tetrahedron0 (face0 cube)
239 t3 = tetrahedron3 (face0 cube)
240 t0' = Tetrahedron cube (v3 t0) (v2 t0) (v1 t0) (v0 t0)
241 t3' = Tetrahedron cube (v3 t3) (v2 t3) (v1 t3) (v0 t3)
242
243 -- | Given in Sorokina and Zeilfelder, p. 79.
244 prop_c1101_identity :: Cube -> Bool
245 prop_c1101_identity cube =
246 c t0' 1 1 0 1 ~= (c t0' 1 1 0 1 + c t3' 1 1 0 1) / 2
247 where
248 t0 = tetrahedron0 (face0 cube)
249 t3 = tetrahedron3 (face0 cube)
250 t0' = Tetrahedron cube (v3 t0) (v2 t0) (v1 t0) (v0 t0)
251 t3' = Tetrahedron cube (v3 t3) (v2 t3) (v1 t3) (v0 t3)
252
253
254 -- | Given in Sorokina and Zeilfelder, p. 79.
255 prop_c1200_identity2 :: Cube -> Bool
256 prop_c1200_identity2 cube =
257 c t0' 1 1 1 0 ~= (c t0' 1 1 1 0 + c t3' 1 1 1 0) / 2
258 where
259 t0 = tetrahedron0 (face0 cube)
260 t3 = tetrahedron3 (face0 cube)
261 t0' = Tetrahedron cube (v3 t0) (v2 t0) (v1 t0) (v0 t0)
262 t3' = Tetrahedron cube (v3 t3) (v2 t3) (v1 t3) (v0 t3)
263
264
265 -- | Given in Sorokina and Zeilfelder, p. 79.
266 prop_c2100_identity2 :: Cube -> Bool
267 prop_c2100_identity2 cube =
268 c t0' 2 1 0 0 ~= (c t0' 2 0 1 0 + c t3' 2 0 1 0) / 2
269 where
270 t0 = tetrahedron0 (face0 cube)
271 t3 = tetrahedron3 (face0 cube)
272 t0' = Tetrahedron cube (v3 t0) (v2 t0) (v1 t0) (v0 t0)
273 t3' = Tetrahedron cube (v3 t3) (v2 t3) (v1 t3) (v0 t3)
274
275
276 -- | Given in Sorokina and Zeilfelder, p. 79.
277 prop_c3000_identity :: Cube -> Bool
278 prop_c3000_identity cube =
279 c t0' 3 0 0 0 ~= c t0' 2 1 0 0 + c t2' 2 1 0 0 - ((c t0' 2 0 1 0 + c t0' 2 0 0 1)/ 2)
280 where
281 t0 = tetrahedron0 (face0 cube)
282 t2 = tetrahedron2 (face5 cube)
283 t0' = Tetrahedron cube (v3 t0) (v2 t0) (v1 t0) (v0 t0)
284 t2' = Tetrahedron cube (v3 t2) (v2 t2) (v1 t2) (v0 t2)
285
286
287 -- | Given in Sorokina and Zeilfelder, p. 79.
288 prop_c2010_identity :: Cube -> Bool
289 prop_c2010_identity cube =
290 c t0' 2 0 1 0 ~= c t0' 1 1 1 0 + c t2' 1 1 1 0 - ((c t0' 1 0 2 0 + c t0' 1 0 1 1)/ 2)
291 where
292 t0 = tetrahedron0 (face0 cube)
293 t2 = tetrahedron2 (face5 cube)
294 t0' = Tetrahedron cube (v3 t0) (v2 t0) (v1 t0) (v0 t0)
295 t2' = Tetrahedron cube (v3 t2) (v2 t2) (v1 t2) (v0 t2)
296
297
298 -- | Given in Sorokina and Zeilfelder, p. 79.
299 prop_c2001_identity :: Cube -> Bool
300 prop_c2001_identity cube =
301 c t0' 2 0 0 1 ~= c t0' 1 1 0 1 + c t2' 1 1 0 1 - ((c t0' 1 0 0 2 + c t0' 1 0 1 1)/ 2)
302 where
303 t0 = tetrahedron0 (face0 cube)
304 t2 = tetrahedron2 (face5 cube)
305 t0' = Tetrahedron cube (v3 t0) (v2 t0) (v1 t0) (v0 t0)
306 t2' = Tetrahedron cube (v3 t2) (v2 t2) (v1 t2) (v0 t2)
307
308 -- | Given in Sorokina and Zeilfelder, p. 79.
309 prop_c1020_identity :: Cube -> Bool
310 prop_c1020_identity cube =
311 c t0' 1 0 2 0 ~= c t0' 0 1 2 0 + c t2' 0 1 2 0 - ((c t0' 0 0 3 0 + c t0' 0 0 2 1)/ 2)
312 where
313 t0 = tetrahedron0 (face0 cube)
314 t2 = tetrahedron2 (face5 cube)
315 t0' = Tetrahedron cube (v3 t0) (v2 t0) (v1 t0) (v0 t0)
316 t2' = Tetrahedron cube (v3 t2) (v2 t2) (v1 t2) (v0 t2)
317
318
319 -- | Given in Sorokina and Zeilfelder, p. 79.
320 prop_c1002_identity :: Cube -> Bool
321 prop_c1002_identity cube =
322 c t0' 1 0 0 2 ~= c t0' 0 1 0 2 + c t2' 0 1 0 2 - ((c t0' 0 0 0 3 + c t0' 0 0 1 2)/ 2)
323 where
324 t0 = tetrahedron0 (face0 cube)
325 t2 = tetrahedron2 (face5 cube)
326 t0' = Tetrahedron cube (v3 t0) (v2 t0) (v1 t0) (v0 t0)
327 t2' = Tetrahedron cube (v3 t2) (v2 t2) (v1 t2) (v0 t2)
328
329
330 -- | Given in Sorokina and Zeilfelder, p. 79.
331 prop_c1011_identity :: Cube -> Bool
332 prop_c1011_identity cube =
333 c t0' 1 0 1 1 ~= c t0' 0 1 1 1 + c t2' 0 1 1 1 - ((c t0' 0 0 1 2 + c t0' 0 0 2 1)/ 2)
334 where
335 t0 = tetrahedron0 (face0 cube)
336 t2 = tetrahedron2 (face5 cube)
337 t0' = Tetrahedron cube (v3 t0) (v2 t0) (v1 t0) (v0 t0)
338 t2' = Tetrahedron cube (v3 t2) (v2 t2) (v1 t2) (v0 t2)
339
340
341 -- | Given in Sorokina and Zeilfelder, p. 80.
342 prop_c0120_identity2 :: Cube -> Bool
343 prop_c0120_identity2 cube =
344 c t0' 0 1 2 0 ~= (c t0' 1 0 2 0 + c t1' 1 0 2 0) / 2
345 where
346 t0 = tetrahedron0 (face0 cube)
347 t1 = tetrahedron0 (face2 (top cube))
348 t0' = Tetrahedron cube (v3 t0) (v2 t0) (v1 t0) (v0 t0)
349 t1' = Tetrahedron cube (v3 t1) (v2 t1) (v0 t1) (v1 t1)
350
351
352 -- | Given in Sorokina and Zeilfelder, p. 80.
353 prop_c0102_identity2 :: Cube -> Bool
354 prop_c0102_identity2 cube =
355 c t0' 0 1 0 2 ~= (c t0' 1 0 0 2 + c t1' 1 0 0 2) / 2
356 where
357 t0 = tetrahedron0 (face0 cube)
358 t1 = tetrahedron0 (face2 (top cube))
359 t0' = Tetrahedron cube (v3 t0) (v2 t0) (v1 t0) (v0 t0)
360 t1' = Tetrahedron cube (v3 t1) (v2 t1) (v0 t1) (v1 t1)
361
362
363 -- | Given in Sorokina and Zeilfelder, p. 80.
364 prop_c0111_identity :: Cube -> Bool
365 prop_c0111_identity cube =
366 c t0' 0 1 1 1 ~= (c t0' 1 0 1 1 + c t1' 1 0 1 1) / 2
367 where
368 t0 = tetrahedron0 (face0 cube)
369 t1 = tetrahedron0 (face2 (top cube))
370 t0' = Tetrahedron cube (v3 t0) (v2 t0) (v1 t0) (v0 t0)
371 t1' = Tetrahedron cube (v3 t1) (v2 t1) (v0 t1) (v1 t1)
372
373
374 -- | Given in Sorokina and Zeilfelder, p. 80.
375 prop_c0210_identity2 :: Cube -> Bool
376 prop_c0210_identity2 cube =
377 c t0 0 2 1 0 ~= (c t0 1 1 1 0 + c t1 1 1 1 0) / 2
378 where
379 t0 = tetrahedron0 (face0 cube)
380 t1 = tetrahedron0 (face2 (top cube))
381 t0' = Tetrahedron cube (v3 t0) (v2 t0) (v1 t0) (v0 t0)
382 t1' = Tetrahedron cube (v3 t1) (v2 t1) (v0 t1) (v1 t1)
383
384
385 -- | Given in Sorokina and Zeilfelder, p. 80.
386 prop_c0201_identity2 :: Cube -> Bool
387 prop_c0201_identity2 cube =
388 c t0 0 2 0 1 ~= (c t0 1 1 0 1 + c t1 1 1 0 1) / 2
389 where
390 t0 = tetrahedron0 (face0 cube)
391 t1 = tetrahedron0 (face2 (top cube))
392 t0' = Tetrahedron cube (v3 t0) (v2 t0) (v1 t0) (v0 t0)
393 t1' = Tetrahedron cube (v3 t1) (v2 t1) (v0 t1) (v1 t1)
394
395
396 -- | Given in Sorokina and Zeilfelder, p. 80.
397 prop_c0300_identity3 :: Cube -> Bool
398 prop_c0300_identity3 cube =
399 c t0 0 3 0 0 ~= (c t0 1 2 0 0 + c t1 1 2 0 0) / 2
400 where
401 t0 = tetrahedron0 (face0 cube)
402 t1 = tetrahedron0 (face2 (top cube))
403 t0' = Tetrahedron cube (v3 t0) (v2 t0) (v1 t0) (v0 t0)
404 t1' = Tetrahedron cube (v3 t1) (v2 t1) (v0 t1) (v1 t1)