--------------------------------------------------------------------------------
-- |
-- Module      :  HGeometry.Kernel.Test.Box
-- Copyright   :  (C) Frank Staals
-- License     :  see the LICENSE file
-- Maintainer  :  Frank Staals
--
-- Helper Utilities
--
--------------------------------------------------------------------------------
module HGeometry.Kernel.Test.Box where

import Control.Lens
import Data.Ratio
import HGeometry.Box
import HGeometry.Point
import HGeometry.Vector
import Test.QuickCheck

--------------------------------------------------------------------------------

--  | Generate an arbitrary point in the given rectangle.
arbitraryPointInBoundingBox   :: Rectangle (Point 2 Rational) -> Gen (Point 2 Rational)
arbitraryPointInBoundingBox :: Rectangle (Point 2 Rational) -> Gen (Point 2 Rational)
arbitraryPointInBoundingBox Rectangle (Point 2 Rational)
b = do
  ZeroToOne rX <- Gen ZeroToOne
forall a. Arbitrary a => Gen a
arbitrary
  ZeroToOne rY <- arbitrary
  let minPt        = Rectangle (Point 2 Rational)
bRectangle (Point 2 Rational)
-> Getting
     (Point 2 Rational)
     (Rectangle (Point 2 Rational))
     (Point 2 Rational)
-> Point 2 Rational
forall s a. s -> Getting a s a -> a
^.Getting
  (Point 2 Rational)
  (Rectangle (Point 2 Rational))
  (Point 2 Rational)
forall box point. HasMinPoint box point => Lens' box point
Lens' (Rectangle (Point 2 Rational)) (Point 2 Rational)
minPoint
      offsetVector = Rational -> Rational -> Vector 2 Rational
forall r. r -> r -> Vector 2 r
Vector2 (Rectangle (Point 2 Rational) -> Rational
forall box point (d :: Natural) r.
(Box_ box point, Point_ point d r, 0 <= (d - 1),
 Functor (Vector d), Num r) =>
box -> r
width Rectangle (Point 2 Rational)
b Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
* Rational
rX) (Rectangle (Point 2 Rational) -> Rational
forall box point (d :: Natural) r.
(Box_ box point, Point_ point d r, 1 <= (d - 1),
 Functor (Vector d), Num r) =>
box -> r
height Rectangle (Point 2 Rational)
b Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
* Rational
rY)
  pure $ minPt .+^ offsetVector


newtype ZeroToOne = ZeroToOne Rational

instance Show ZeroToOne where
  show :: ZeroToOne -> String
show (ZeroToOne Rational
r) = Rational -> String
forall a. Show a => a -> String
show Rational
r

instance Arbitrary ZeroToOne where
  arbitrary :: Gen ZeroToOne
arbitrary = do
    k <- (Integer, Integer) -> Gen Integer
chooseInteger (Integer
0, Integer
granularity)
    pure $ ZeroToOne $ k % granularity
    where
      granularity :: Integer
granularity = Integer
1000000
  shrink :: ZeroToOne -> [ZeroToOne]
shrink (ZeroToOne Rational
1) = []
  shrink (ZeroToOne Rational
0) = []
  shrink (ZeroToOne Rational
r) = [ Rational -> ZeroToOne
ZeroToOne (Rational -> ZeroToOne) -> Rational -> ZeroToOne
forall a b. (a -> b) -> a -> b
$ Integer -> Integer -> Integer
forall a. Integral a => a -> a -> a
div (Rational -> Integer
forall a. Ratio a -> a
numerator Rational
r) Integer
2 Integer -> Integer -> Rational
forall a. Integral a => a -> a -> Ratio a
% Integer -> Integer -> Integer
forall a. Integral a => a -> a -> a
div (Rational -> Integer
forall a. Ratio a -> a
denominator Rational
r) Integer
2]