Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Direction type #186

Merged
merged 23 commits into from
Jun 11, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions diagrams-lib.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ Library
Diagrams.Path,
Diagrams.CubicSpline,
Diagrams.CubicSpline.Internal,
Diagrams.Direction,
Diagrams.Solve,
Diagrams.Tangent,
Diagrams.Transform,
Expand Down
21 changes: 17 additions & 4 deletions src/Diagrams/Angle.hs
Original file line number Diff line number Diff line change
Expand Up @@ -17,22 +17,30 @@ module Diagrams.Angle
Angle
, rad, turn, deg
, fullTurn, fullCircle, angleRatio
, sinA, cosA, tanA, asinA, acosA, atanA
, sinA, cosA, tanA, asinA, acosA, atanA, atan2A
, (@@)
, angleBetween
, HasTheta(..)
) where

import Control.Lens (Iso', Lens', iso, review, (^.))
-- , review , (^.), _1, _2, Lens', lens)
import Control.Lens (Iso', Lens', iso, review, (^.))

import Data.VectorSpace
import Data.Monoid hiding ((<>))
import Data.Semigroup
import Data.VectorSpace

-- | Angles can be expressed in a variety of units. Internally,
-- they are represented in radians.
newtype Angle = Radians Double
deriving (Read, Show, Eq, Ord, Enum, AdditiveGroup)

instance Semigroup Angle where
(<>) = (^+^)

instance Monoid Angle where
mappend = (<>)
mempty = Radians 0

instance VectorSpace Angle where
type Scalar Angle = Double
s *^ Radians t = Radians (s*t)
Expand Down Expand Up @@ -90,6 +98,11 @@ acosA = Radians . acos
atanA :: Double -> Angle
atanA = Radians . atan

-- | @atan2A n d@ is the @Angle with tangent @n/d@, unless d is 0, in
-- which case it is ±π/2.
atan2A :: Double -> Double -> Angle
atan2A n d = Radians $ atan2 n d

-- | @30 \@\@ deg@ is an @Angle@ of the given measure and units.
--
-- More generally, @\@\@@ reverses the @Iso\'@ on its right, and
Expand Down
11 changes: 11 additions & 0 deletions src/Diagrams/Combinators.hs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ module Diagrams.Combinators
, atop
, beneath
, beside
, atDirection

-- * n-ary operations
, appends
Expand Down Expand Up @@ -57,6 +58,7 @@ import Data.VectorSpace

import Diagrams.Core
import Diagrams.Core.Types (QDiagram (QD))
import Diagrams.Direction
import Diagrams.Located
import Diagrams.Path
import Diagrams.Segment (straight)
Expand Down Expand Up @@ -237,6 +239,15 @@ infixl 6 `beneath`
beside :: (Juxtaposable a, Semigroup a) => V a -> a -> a -> a
beside v d1 d2 = d1 <> juxtapose v d1 d2

-- | Place two diagrams (or other juxtaposable objects) adjacent to
-- one another, with the second diagram placed in the direction 'd'
-- from the first. The local origin of the resulting combined
-- diagram is the same as the local origin of the first. See the
-- documentation of 'beside' for more information.
atDirection :: (Juxtaposable a, Semigroup a, InnerSpace (V a), Floating (Scalar (V a))) =>
Direction (V a) -> a -> a -> a
atDirection = beside . fromDirection

------------------------------------------------------------
-- Combining multiple objects
------------------------------------------------------------
Expand Down
60 changes: 60 additions & 0 deletions src/Diagrams/Direction.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE TypeFamilies #-}
-----------------------------------------------------------------------------
-- |
-- Module : Diagrams.Direction
-- Copyright : (c) 2014 diagrams-lib team (see LICENSE)
-- License : BSD-style (see LICENSE)
-- Maintainer : diagrams-discuss@googlegroups.com
--
-- Type for representing directions, polymorphic in vector space
--
-----------------------------------------------------------------------------

module Diagrams.Direction
( Direction
, _Dir
, direction, fromDirection
, angleBetweenDirs
) where

import Control.Lens (Iso', iso)
import Data.VectorSpace

import Diagrams.Angle
import Diagrams.Core

--------------------------------------------------------------------------------
-- Direction

-- | A vector is described by a @Direction@ and a magnitude. So we
-- can think of a @Direction@ as a vector that has forgotten its
-- magnitude. @Direction@s can be used with 'fromDirection' and the
-- lenses provided by its instances.
newtype Direction v = Direction v

type instance V (Direction v) = v

instance (Transformable v, V (Direction v) ~ V v) => Transformable (Direction v) where
transform t (Direction v) = Direction (transform t v)

-- | _Dir is provided to allow efficient implementations of functions
-- in particular vector-spaces, but should be used with care as it
-- exposes too much information.
_Dir :: Iso' (Direction v) v
_Dir = iso (\(Direction v) -> v) Direction

-- | @direction v@ is the direction in which @v@ points. Returns an
-- unspecified value when given the zero vector as input.
direction :: v -> Direction v
direction = Direction

-- | @fromDirection d@ is the unit vector in the direction @d@.
fromDirection :: (InnerSpace v, Floating (Scalar v)) => Direction v -> v
fromDirection (Direction v) = normalized v

-- | compute the positive angle between the two directions in their common plane
angleBetweenDirs :: (InnerSpace v, Scalar v ~ Double) =>
Direction v -> Direction v -> Angle
angleBetweenDirs d1 d2 = angleBetween (fromDirection d1) (fromDirection d2)
3 changes: 3 additions & 0 deletions src/Diagrams/Prelude.hs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@ module Diagrams.Prelude
, module Diagrams.Angle
-- | Convenience infix operators for working with coordinates.
, module Diagrams.Coordinates
-- | Directions, distinguished from angles or vectors
, module Diagrams.Direction

-- | A wide range of things (shapes, transformations,
-- combinators) specific to creating two-dimensional
Expand Down Expand Up @@ -132,6 +134,7 @@ import Diagrams.Combinators
import Diagrams.Coordinates
import Diagrams.CubicSpline
import Diagrams.Deform
import Diagrams.Direction
import Diagrams.Envelope
import Diagrams.Located
import Diagrams.Names
Expand Down
2 changes: 2 additions & 0 deletions src/Diagrams/ThreeD.hs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ module Diagrams.ThreeD
module Diagrams.ThreeD.Align
, module Diagrams.ThreeD.Attributes
, module Diagrams.ThreeD.Camera
, module Diagrams.ThreeD.Deform
, module Diagrams.ThreeD.Light
, module Diagrams.ThreeD.Shapes
, module Diagrams.ThreeD.Transform
Expand All @@ -45,6 +46,7 @@ module Diagrams.ThreeD
import Diagrams.ThreeD.Align
import Diagrams.ThreeD.Attributes
import Diagrams.ThreeD.Camera
import Diagrams.ThreeD.Deform
import Diagrams.ThreeD.Light
import Diagrams.ThreeD.Shapes
import Diagrams.ThreeD.Transform
Expand Down
7 changes: 4 additions & 3 deletions src/Diagrams/ThreeD/Camera.hs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import Data.Typeable

import Diagrams.Angle
import Diagrams.Core
import Diagrams.Direction
import Diagrams.ThreeD.Types
import Diagrams.ThreeD.Vector

Expand Down Expand Up @@ -118,13 +119,13 @@ mm50Wide = PerspectiveLens (43.2 @@ deg) (27 @@ deg)
-- aspect ratio of 4:3, for VGA and similar computer resulotions.
mm50Narrow = PerspectiveLens (36 @@ deg) (27 @@ deg)

camForward :: Camera l -> Direction
camForward :: Camera l -> Direction R3
camForward = direction . forward

camUp :: Camera l -> Direction
camUp :: Camera l -> Direction R3
camUp = direction . up

camRight :: Camera l -> Direction
camRight :: Camera l -> Direction R3
camRight c = direction right where
right = cross3 (forward c) (up c)

Expand Down
3 changes: 2 additions & 1 deletion src/Diagrams/ThreeD/Light.hs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import Data.Monoid
import Data.Typeable

import Diagrams.Core
import Diagrams.Direction
import Diagrams.ThreeD.Types

data PointLight = PointLight P3 (Colour Double)
Expand Down Expand Up @@ -48,7 +49,7 @@ pointLight c = mkQD (Prim $ PointLight origin c) mempty mempty mempty

-- | Construct a Diagram with a single ParallelLight, which takes up no space.
parallelLight :: (Backend b R3, Renderable ParallelLight b)
=> Direction -- ^ The direction in which the light travels.
=> Direction R3 -- ^ The direction in which the light travels.
-> Colour Double -- ^ The color of the light.
-> Diagram b R3
parallelLight d c = mkQD (Prim $ ParallelLight (fromDirection d) c)
Expand Down
26 changes: 17 additions & 9 deletions src/Diagrams/ThreeD/Transform.hs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ import Diagrams.Core
import qualified Diagrams.Core.Transform as T

import Diagrams.Angle
import Diagrams.Direction
import Diagrams.Transform
import Diagrams.ThreeD.Types
import Diagrams.Coordinates
Expand Down Expand Up @@ -104,7 +105,7 @@ aboutY ang = fromLinear r (linv r) where
-- passing through @p@.
rotationAbout ::
P3 -- ^ origin of rotation
-> Direction -- ^ direction of rotation axis
-> Direction R3 -- ^ direction of rotation axis
-> Angle -- ^ angle of rotation
-> T3
rotationAbout p d a
Expand All @@ -123,23 +124,30 @@ rotationAbout p d a
-- | @pointAt about initial final@ produces a rotation which brings
-- the direction @initial@ to point in the direction @final@ by first
-- panning around @about@, then tilting about the axis perpendicular
-- to initial and final. In particular, if this can be accomplished
-- to @about@ and @final@. In particular, if this can be accomplished
-- without tilting, it will be, otherwise if only tilting is
-- necessary, no panning will occur. The tilt will always be between
-- ± 1/4 turn.
pointAt :: Direction -> Direction -> Direction -> T3
pointAt :: Direction R3 -> Direction R3 -> Direction R3 -> T3
pointAt a i f = pointAt' (fromDirection a) (fromDirection i) (fromDirection f)

-- | pointAt' has the same behavior as 'pointAt', but takes vectors
-- instead of directions.
pointAt' :: R3 -> R3 -> R3 -> T3
pointAt' about initial final = tilt <> pan where
inPanPlane = final ^-^ project final initial
panAngle = angleBetween initial inPanPlane
pointAt' about initial final = pointAtUnit (normalized about) (normalized initial) (normalized final)

-- | pointAtUnit has the same behavior as @pointAt@, but takes unit vectors.
pointAtUnit :: R3 -> R3 -> R3 -> T3
pointAtUnit about initial final = tilt <> pan where
-- rotating u by (signedAngle rel u v) about rel gives a vector in the direction of v
signedAngle rel u v = signum (cross3 u v <.> rel) *^ angleBetween u v
inPanPlaneF = final ^-^ project about final
inPanPlaneI = initial ^-^ project about initial
panAngle = signedAngle about inPanPlaneI inPanPlaneF
pan = rotationAbout origin (direction about) panAngle
tiltAngle = angleBetween initial inPanPlane
tiltDir = direction $ cross3 inPanPlane about
tilt = rotationAbout origin tiltDir tiltAngle
tiltAngle = signedAngle tiltAxis (transform pan initial) final
tiltAxis = cross3 final about
tilt = rotationAbout origin (direction tiltAxis) tiltAngle

-- Scaling -------------------------------------------------

Expand Down
33 changes: 3 additions & 30 deletions src/Diagrams/ThreeD/Types.hs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TypeFamilies #-}
Expand All @@ -26,8 +25,6 @@ module Diagrams.ThreeD.Types
, T3
, r3Iso, p3Iso

-- * Directions in 3D
, Direction, direction, fromDirection, angleBetweenDirs
-- * other coördinate systems
, Spherical(..), Cylindrical(..), HasPhi(..)
) where
Expand All @@ -37,6 +34,7 @@ import Control.Lens (Iso', Lens', iso, over

import Diagrams.Core
import Diagrams.Angle
import Diagrams.Direction
import Diagrams.TwoD.Types (R2)
import Diagrams.Coordinates

Expand Down Expand Up @@ -122,18 +120,6 @@ instance Transformable R3 where
instance HasCross3 R3 where
cross3 u v = r3 $ cross3 (unr3 u) (unr3 v)

--------------------------------------------------------------------------------
-- Direction

-- | A @Direction@ represents directions in R3. The constructor is
-- not exported; @Direction@s can be used with 'fromDirection' and the
-- lenses provided by its instances.
data Direction = Direction R3

-- | Not exported
_Dir :: Iso' Direction R3
_Dir = iso (\(Direction v) -> v) Direction

instance HasX R3 where
_x = r3Iso . _1

Expand Down Expand Up @@ -203,21 +189,8 @@ instance Cylindrical P3 where
instance Spherical P3 where
spherical = _relative origin . spherical

instance HasTheta Direction where
instance HasTheta (Direction R3) where
_theta = _Dir . _theta

instance HasPhi Direction where
instance HasPhi (Direction R3) where
_phi = _Dir . _phi

-- | @direction v@ is the direction in which @v@ points. Returns an
-- unspecified value when given the zero vector as input.
direction :: R3 -> Direction
direction = Direction

-- | @fromDirection d@ is the unit vector in the direction @d@.
fromDirection :: Direction -> R3
fromDirection (Direction v) = normalized v

-- | compute the positive angle between the two directions in their common plane
angleBetweenDirs :: Direction -> Direction -> Angle
angleBetweenDirs d1 d2 = angleBetween (fromDirection d1) (fromDirection d2)
5 changes: 2 additions & 3 deletions src/Diagrams/TwoD.hs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ module Diagrams.TwoD
, P2, p2, unp2, mkP2
, T2
, unitX, unitY, unit_X, unit_Y
, direction, fromDirection
, xDir

-- * Angles
, tau
Expand All @@ -92,7 +92,6 @@ module Diagrams.TwoD
, ellipseXY
, arc
, arc'
, arcCW
, wedge
, arcBetween
, annularWedge
Expand Down Expand Up @@ -200,7 +199,7 @@ module Diagrams.TwoD

-- * Combinators
-- ** Combining multiple diagrams
, (===), (|||), atAngle
, (===), (|||)
, hcat, hcat'
, vcat, vcat'

Expand Down
Loading