File: Segment.hs

package info (click to toggle)
haskell-diagrams-lib 1.4.6.2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,256 kB
  • sloc: haskell: 8,263; makefile: 2
file content (54 lines) | stat: -rw-r--r-- 1,668 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
{-# LANGUAGE FlexibleContexts  #-}
{-# LANGUAGE FlexibleInstances #-}

{-# OPTIONS_GHC -fno-warn-orphans #-}

module Diagrams.Test.TwoD.Segment
    (
      tests
    ) where

import qualified Test.QuickCheck.Property as Q
import           Test.Tasty               (TestTree)
import           Test.Tasty.QuickCheck

import           Diagrams.Prelude
import           Diagrams.TwoD.Segment

newtype InBox = InBox { unInBox :: Double }

instance Arbitrary InBox where
  arbitrary = InBox <$> choose (-1, 1)

instance Arbitrary (Point V2 Double) where
  arbitrary = curry p2 <$> (unInBox <$> arbitrary)
                       <*> (unInBox <$> arbitrary)

instance Arbitrary (FixedSegment V2 Double) where
   arbitrary = oneof [FLinear <$> arbitrary <*> arbitrary, FCubic <$> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary]

epsT, epsE :: Double
epsT = 1.0e-9 -- parameter space epsilon
epsE = 1.0e-8 -- Euclidean space epsilon

(.=~.) :: P2 Double -> P2 Double -> Bool
x .=~. y = norm (x .-. y) < epsE

tests :: [TestTree]
tests =
    [ testProperty "segmentSegment" $
        \a b -> validateIntersections a b (segmentSegment epsT a b)
    ]

validateIntersections :: FixedSegment V2 Double -> FixedSegment V2 Double -> [(Double, Double, P2 Double)] -> Q.Result
validateIntersections _ _ [] = Q.rejected -- TODO: check for false negatives (rasterize both and look for overlap?)
validateIntersections a b isects = go isects
  where
    go [] = Q.succeeded
    go ((ta,tb,p):is)
      | and [ 0 <= ta && ta <= 1
            , 0 <= tb && tb <= 1
            , a `atParam` ta .=~. p
            , b `atParam` tb .=~. p
            ] = go is
      | otherwise = Q.failed