]> gitweb.michael.orlitzky.com - spline3.git/blobdiff - src/Tetrahedron.hs
Add the "number" field for tetrahedra.
[spline3.git] / src / Tetrahedron.hs
index 73ed58863595cab2da3bd8a4a0e98cd2f5f69ad4..d468f0c570a920fe3967fdd7e20973ef2cd9945e 100644 (file)
@@ -3,21 +3,30 @@ where
 
 import Numeric.LinearAlgebra hiding (i, scale)
 import Prelude hiding (LT)
-import Test.QuickCheck (Arbitrary(..), Gen)
+import Test.QuickCheck (Arbitrary(..), Gen, choose)
 
 import Cardinal
+import Comparisons (nearly_ge)
 import FunctionValues
 import Misc (factorial)
 import Point
 import RealFunction
 import ThreeDimensional
 
-data Tetrahedron = Tetrahedron { fv :: FunctionValues,
-                                 v0 :: Point,
-                                 v1 :: Point,
-                                 v2 :: Point,
-                                 v3 :: Point }
-                   deriving (Eq)
+data Tetrahedron =
+  Tetrahedron { fv :: FunctionValues,
+                v0 :: Point,
+                v1 :: Point,
+                v2 :: Point,
+                v3 :: Point,
+                precomputed_volume :: Double,
+
+                -- | Between 0 and 23; used to quickly determine which
+                --   tetrahedron I am in the parent 'Cube' without
+                --   having to compare them all.
+                number :: Int
+              }
+    deriving (Eq)
 
 
 instance Arbitrary Tetrahedron where
@@ -27,7 +36,13 @@ instance Arbitrary Tetrahedron where
       rnd_v2 <- arbitrary :: Gen Point
       rnd_v3 <- arbitrary :: Gen Point
       rnd_fv <- arbitrary :: Gen FunctionValues
-      return (Tetrahedron rnd_fv rnd_v0 rnd_v1 rnd_v2 rnd_v3)
+      rnd_no <- choose (0,23)
+
+      -- We can't assign an incorrect precomputed volume,
+      -- so we have to calculate the correct one here.
+      let t' = Tetrahedron rnd_fv rnd_v0 rnd_v1 rnd_v2 rnd_v3 0 rnd_no
+      let vol = volume t'
+      return (Tetrahedron rnd_fv rnd_v0 rnd_v1 rnd_v2 rnd_v3 vol rnd_no)
 
 
 instance Show Tetrahedron where
@@ -42,7 +57,28 @@ instance Show Tetrahedron where
 instance ThreeDimensional Tetrahedron where
     center t = ((v0 t) + (v1 t) + (v2 t) + (v3 t)) `scale` (1/4)
     contains_point t p =
-        (b0 t p) >= 0 && (b1 t p) >= 0 && (b2 t p) >= 0 && (b3 t p) >= 0
+      b0_unscaled `nearly_ge` 0 &&
+      b1_unscaled `nearly_ge` 0 &&
+      b2_unscaled `nearly_ge` 0 &&
+      b3_unscaled `nearly_ge` 0
+      where
+        -- Drop the useless division and volume calculation that we
+        -- would do if we used the regular b0,..b3 functions.
+        b0_unscaled :: Double
+        b0_unscaled = volume inner_tetrahedron
+          where inner_tetrahedron = t { v0 = p }
+
+        b1_unscaled :: Double
+        b1_unscaled = volume inner_tetrahedron
+          where inner_tetrahedron = t { v1 = p }
+
+        b2_unscaled :: Double
+        b2_unscaled = volume inner_tetrahedron
+          where inner_tetrahedron = t { v2 = p }
+
+        b3_unscaled :: Double
+        b3_unscaled = volume inner_tetrahedron
+          where inner_tetrahedron = t { v3 = p }
 
 
 polynomial :: Tetrahedron -> (RealFunction Point)
@@ -243,27 +279,27 @@ volume t
 
 -- | The barycentric coordinates of a point with respect to v0.
 b0 :: Tetrahedron -> (RealFunction Point)
-b0 t point = (volume inner_tetrahedron) / (volume t)
+b0 t point = (volume inner_tetrahedron) / (precomputed_volume t)
              where
                inner_tetrahedron = t { v0 = point }
 
 
 -- | The barycentric coordinates of a point with respect to v1.
 b1 :: Tetrahedron -> (RealFunction Point)
-b1 t point = (volume inner_tetrahedron) / (volume t)
+b1 t point = (volume inner_tetrahedron) / (precomputed_volume t)
              where
                inner_tetrahedron = t { v1 = point }
 
 
 -- | The barycentric coordinates of a point with respect to v2.
 b2 :: Tetrahedron -> (RealFunction Point)
-b2 t point = (volume inner_tetrahedron) / (volume t)
+b2 t point = (volume inner_tetrahedron) / (precomputed_volume t)
              where
                inner_tetrahedron = t { v2 = point }
 
 
 -- | The barycentric coordinates of a point with respect to v3.
 b3 :: Tetrahedron -> (RealFunction Point)
-b3 t point = (volume inner_tetrahedron) / (volume t)
+b3 t point = (volume inner_tetrahedron) / (precomputed_volume t)
              where
                inner_tetrahedron = t { v3 = point }