Skip to content

Commit

Permalink
Mostly finished refactoring (still needs language/import cleanups bef…
Browse files Browse the repository at this point in the history
…ore merge, plus review)
  • Loading branch information
Mathnerd314 committed May 31, 2014
1 parent 2d7a1a0 commit 06f0536
Show file tree
Hide file tree
Showing 41 changed files with 940 additions and 849 deletions.
3 changes: 3 additions & 0 deletions diagrams-lib.cabal
Expand Up @@ -55,6 +55,7 @@ Library
Diagrams.Query,
Diagrams.TwoD,
Diagrams.TwoD.Types,
Diagrams.TwoD.Types.Double,
Diagrams.TwoD.Align,
Diagrams.TwoD.Arrow,
Diagrams.TwoD.Arrowheads,
Expand Down Expand Up @@ -85,6 +86,7 @@ Library
Diagrams.ThreeD.Shapes,
Diagrams.ThreeD.Transform,
Diagrams.ThreeD.Types,
Diagrams.ThreeD.Types.Double,
Diagrams.ThreeD.Vector,
Diagrams.ThreeD,
Diagrams.Animation,
Expand Down Expand Up @@ -116,6 +118,7 @@ Library
if impl(ghc < 7.6)
Build-depends: ghc-prim
Hs-source-dirs: src
ghc-options: -Wall -Werror
default-language: Haskell2010
-- default-extensions: FlexibleContexts, FlexibleInstances, MultiParamTypeClasses, TypeFamilies
other-extensions: BangPatterns, CPP, DefaultSignatures, DeriveDataTypeable, DeriveFunctor, DeriveGeneric, EmptyDataDecls, ExistentialQuantification, GADTs,
Expand Down
10 changes: 9 additions & 1 deletion src/Diagrams/Angle.hs
Expand Up @@ -26,13 +26,14 @@ module Diagrams.Angle
, HasPhi(..)
) where

import Control.Lens (Iso', Lens', iso, review, (^.))
import Control.Lens (Iso', Lens', iso, review)

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

import Diagrams.Core.V
import Diagrams.Points

-- | Angles can be expressed in a variety of units. Internally,
-- they are represented in radians.
Expand Down Expand Up @@ -136,3 +137,10 @@ class HasTheta t where
class HasPhi t where
_phi :: Lens' t (Angle (Scalar (V t)))

-- Point instances
instance (HasTheta v, v ~ V v) => HasTheta (Point v) where
_theta = _pIso . _theta

instance (HasPhi v, v ~ V v) => HasPhi (Point v) where
_phi = _pIso . _phi

9 changes: 5 additions & 4 deletions src/Diagrams/Animation.hs
@@ -1,6 +1,7 @@
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE ConstraintKinds, TypeFamilies, FlexibleContexts #-}
-----------------------------------------------------------------------------
-- |
-- Module : Diagrams.Animation
Expand Down Expand Up @@ -109,18 +110,18 @@ animEnvelope' r a = withEnvelope (simulate r a) <$> a
--
-- Uses 30 samples per time unit by default; to adjust this number
-- see 'animRect''.
animRect :: (TrailLike t, Enveloped t, Transformable t, Monoid t, V t ~ R2
animRect :: (TrailLike t, Enveloped t, Transformable t, Monoid t, V t ~ v, R2Ish v
, Monoid' m)
=> QAnimation b R2 m -> t
=> QAnimation b v m -> t
animRect = animRect' 30

-- | Like 'animRect', but with an adjustible sample rate. The first
-- parameter is the number of samples per time unit to use. Lower
-- rates will be faster but less accurate; higher rates are more
-- accurate but slower.
animRect' :: (TrailLike t, Enveloped t, Transformable t, Monoid t, V t ~ R2
animRect' :: (TrailLike t, Enveloped t, Transformable t, Monoid t, V t ~ v, R2Ish v
, Monoid' m)
=> Rational -> QAnimation b R2 m -> t
=> Rational -> QAnimation b v m -> t
animRect' r anim
| null results = rect 1 1
| otherwise = boxFit (foldMap boundingBox results) (rect 1 1)
Expand Down
42 changes: 32 additions & 10 deletions src/Diagrams/Coordinates.hs
Expand Up @@ -23,17 +23,10 @@ module Diagrams.Coordinates
import Control.Lens (Lens')
import Data.VectorSpace

import Diagrams.Core.Points
import Diagrams.Points
import Data.AffineSpace.Point
import Diagrams.Core.V

-- | A pair of values, with a convenient infix (left-associative)
-- data constructor.
data a :& b = a :& b
deriving (Eq, Ord, Show)

infixl 7 :&


-- | Types which are instances of the @Coordinates@ class can be
-- constructed using '^&' (for example, a three-dimensional vector
-- could be constructed by @1 ^& 6 ^& 3@), and deconstructed using
Expand Down Expand Up @@ -78,14 +71,30 @@ class Coordinates c where

infixl 7 ^&

-- | A pair of values, with a convenient infix (left-associative)
-- data constructor.
data a :& b = a :& b
deriving (Eq, Ord, Show)

infixl 7 :&

-- Instance for :& (the buck stops here)
instance Coordinates (a :& b) where
type FinalCoord (a :& b) = b
type PrevDim (a :& b) = a
type Decomposition (a :& b) = a :& b
x ^& y = x :& y
coords (x :& y) = x :& y


-- Some standard instances for plain old tuples

instance Coordinates (a,b) where
type FinalCoord (a,b) = b
type PrevDim (a,b) = a
type Decomposition (a,b) = a :& b

x ^& y = (x,y)
x ^& y = (x,y)
coords (x,y) = x :& y

instance Coordinates (a,b,c) where
Expand Down Expand Up @@ -128,3 +137,16 @@ class HasZ t where
-- magnitude of a vector, or the distance from the origin of a point.
class HasR t where
_r :: Lens' t (Scalar (V t))

instance (HasX v, v ~ V v) => HasX (Point v) where
_x = _pIso . _x

instance (HasY v, v ~ V v) => HasY (Point v) where
_y = _pIso . _y

instance (HasZ v, v ~ V v) => HasZ (Point v) where
_z = _pIso . _z

instance (HasR v, v ~ V v) => HasR (Point v) where
_r = _pIso . _r

7 changes: 6 additions & 1 deletion src/Diagrams/Points.hs
Expand Up @@ -20,17 +20,22 @@ module Diagrams.Points
-- * Point-related utilities
, centroid
, pointDiagram

, _pIso
) where

import Diagrams.Core (pointDiagram)
import Diagrams.Core.Points

import Control.Arrow ((&&&))
import Control.Lens (Iso', iso)

import Data.AffineSpace.Point
import Data.VectorSpace

-- Point v <-> v
_pIso :: Iso' (Point v) v

This comment has been minimized.

Copy link
@bergey

bergey Jun 1, 2014

Member

We have _relative (in Core.Points) which does this in a more general way. I think _relative implies a more geometric intuition, in which the origin of the affine space is only a convenience of representation, not actually a special point. There's a similar comment in the docs for unPoint

This comment has been minimized.

Copy link
@Mathnerd314

Mathnerd314 Jun 1, 2014

Author Contributor

Yeah, but _relative has an AffineSpace constraint, which in turn means an AdditiveGroup constraint on v. This way minimizes the constraints needed to write HasX (Point v). It all depends on how long you want your type signatures to be...

This comment has been minimized.

Copy link
@bergey

bergey Jun 1, 2014

Member

Fair point. I think of the AffineSpace constraint as a freebie, since it's obviously true for any Point v. But it does make the type signature longer.

_pIso = iso unPoint P

-- | The centroid of a set of /n/ points is their sum divided by /n/.
centroid :: (VectorSpace v, Fractional (Scalar v)) => [Point v] -> Point v
centroid = P . uncurry (^/) . (sumV &&& (fromIntegral . length)) . map unPoint
14 changes: 6 additions & 8 deletions src/Diagrams/Tangent.hs
Expand Up @@ -23,7 +23,6 @@ module Diagrams.Tangent
, normalAtStart
, normalAtEnd
, Tangent(..)
, MoreLikeR2
)
where

Expand All @@ -35,7 +34,8 @@ import Diagrams.Located
import Diagrams.Parametric
import Diagrams.Segment
import Diagrams.Trail
import Diagrams.TwoD.Vector (perp, LikeR2)
import Diagrams.TwoD.Vector (perp)
import Diagrams.TwoD.Types (R2Ish)

------------------------------------------------------------
-- Tangent
Expand Down Expand Up @@ -157,8 +157,6 @@ instance ( InnerSpace v
-- Normal
------------------------------------------------------------

type MoreLikeR2 v = (LikeR2 v, InnerSpace v, Floating (Scalar v))

-- | Compute the (unit) normal vector to a segment or trail at a
-- particular parameter.
--
Expand All @@ -172,22 +170,22 @@ type MoreLikeR2 v = (LikeR2 v, InnerSpace v, Floating (Scalar v))
--
-- See the instances listed for the 'Tangent' newtype for more.
normalAtParam
:: (MoreLikeR2 (Codomain (Tangent t)), Parametric (Tangent t))
:: (R2Ish (Codomain (Tangent t)), Parametric (Tangent t))
=> t -> Scalar (V t) -> Codomain (Tangent t)
normalAtParam t p = normize (t `tangentAtParam` p)

-- | Compute the normal vector at the start of a segment or trail.
normalAtStart
:: (MoreLikeR2 (Codomain (Tangent t)), EndValues (Tangent t))
:: (R2Ish (Codomain (Tangent t)), EndValues (Tangent t))
=> t -> Codomain (Tangent t)
normalAtStart = normize . tangentAtStart

-- | Compute the normal vector at the end of a segment or trail.
normalAtEnd
:: (MoreLikeR2 (Codomain (Tangent t)), EndValues (Tangent t))
:: (R2Ish (Codomain (Tangent t)), EndValues (Tangent t))
=> t -> Codomain (Tangent t)
normalAtEnd = normize . tangentAtEnd

-- | Construct a normal vector from a tangent.
normize :: (MoreLikeR2 v) => v -> v
normize :: (R2Ish v) => v -> v
normize = negateV . perp . normalized

5 comments on commit 06f0536

@jeffreyrosenbluth
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you give me the readers digest version of what you are trying to achieve with these changes. This is an awful lot of code to read through, a paragraph or two of explanation would be a great help.

@bergey
Copy link
Member

@bergey bergey commented on 06f0536 Jun 1, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jeffreyrosenbluth There's prior discussion at #50; it's probably enough to read the first comment and the last two.

@jeffreyrosenbluth
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks.

@Mathnerd314
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary of changes, for changelog or reviewing help:

diagrams-lib.cabal: add Diagrams.{Two,Three}D.Double

global changes:

  • Double changed to d, Scalar v, or Scalar (V .) depending on context (not in Colour or GradientStop though; grep to see remaining places)
  • R2 changed to v with (R2Ish v) added to context; similarly for R3
  • Types which hard-coded Double now use v or d; ones with an added type parameter are:
    • Angle
    • PerspectiveLens, OrthoLens
    • PointLight, ParallelLight
    • Ellipsoid, Box, Frustum
    • ArrowOpts, ArrowHT
    • LineWidth, Dashing, DashingA, LGradient, RGradient, Texture, LineTexture, FillTexture
    • DImage
    • OriginOpts, OffsetOpts, ExpandOpts
    • Clip
    • PolyType, PolyOrientation, PolygonOpts, RoundedRectOpts
    • SizeSpec2D
    • Text, FontSize
  • Some utility (not exported) variables' types were commented out / tweaked

Coordinates.hs:

  • Coordinates instance for :&, move stuff around
  • instance (Has* v, v ~ V v) => Has* (Point v) for many Has*, based on _pIso; P2/P3 instances removed

Angle.hs:

  • turn and friends need VectorSpace v, Floating (Scalar v)
  • sinA and friends need Floating v (i.e., v scalar)
  • angleBetween needs InnerSpace v
  • HasPhi moved to Angle.hs, generic HasTheta and HasPhi instances for Point like in Coordinates

Direction.hs:

  • instances for Read, Show, Eq, Ord, HasTheta, HasPhi added. Eq and Ord probably should get tweaked.

Points.hs:

  • _pIso = iso unPoint P added

{Two,Three}D/Types.hs: R{2,3} moved to .Double, methods rewritten to take R{2,3}Ish and use Coords or HasBasis instance
TwoD/Vector.hs: ^& changed to mkR2 (not actually needed)

Arrow.hs:

  • MeasureX was introduced into fromMeasure so widthOfJoint was simpler
  • connectOutside' changed Num's unary (-) to negateV

Arrowheads.hs:

  • parenthesis were added in arrowhead{Dart,Thorn} to avoid Num R2 instance
  • arrowtailBlock uses ScopedTypeVariables

Attributes.hs

  • LineWidth and DashingA Transformable instances use avgScale

Offset.hs

  • Num's unary (-) to negateV in joinSegmentIntersect

TwoD/Transform.hs:

  • shearing{X,Y} had sh, sh', swap moved out to top-level (not exported)

@jeffreyrosenbluth
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, this is very helpful

Please sign in to comment.