ianmackenzie/elm-geometry/1.2.0

NOTE: the latest version is 4.0.0

Frame2d

A Frame2d has an origin point and a pair of X and Y directions (which are always perpendicular to each other). It can be thought of as:

  • A local coordinate system: Most geometric types have associated relativeTo and placeIn functions that convert values of that type from global coordinates to local coordinates in a particular frame, and vice versa.
  • A pair of X and Y axes: It is often convenient to (for example) mirror across the X axis of a frame, or project onto its Y axis. Frames can also themselves be translated, rotated and mirrored!
  • A combined 2D position and orientation: For example, a Frame2d could be used to define the position and orientation of a spaceship in a 2D game. Movement of the ship would then be done by translating and rotating the frame.
type alias Frame2d =
Frame2d

Constants

atOrigin : Frame2d

The global XY frame, centered at the origin.

Frame2d.originPoint Frame2d.atOrigin
--> Point2d.origin


Frame2d.xDirection Frame2d.atOrigin
--> Direction2d.x


Frame2d.yDirection Frame2d.atOrigin
--> Direction2d.y
xy : Frame2d

DEPRECATED: Alias for Frame2d.atOrigin, kept for compatibility. Will be removed in the next major release.

Constructors

atPoint : Point2d -> Frame2d

Construct a frame aligned with the global XY frame but with the given origin point.

point =
    Point2d.fromCoordinates ( 2, 3 )


frame =
    Frame2d.atPoint point


Frame2d.originPoint frame
--> point


Frame2d.xDirection frame
--> Direction2d.x


Frame2d.yDirection frame
--> Direction2d.y
atCoordinates : ( Float, Float ) -> Frame2d

Shorthand for Frame2d.atPoint;

Frame2d.atCoordinates ( x, y )

is equivalent to

Frame2d.atPoint (Point2d.fromCoordinates ( x, y ))
withXDirection : Direction2d -> Point2d -> Frame2d

Construct a frame with the given X axis direction, having the given origin point. The Y axis direction will be constructed by rotating the given X direction 90 degrees counterclockwise:

frame =
    Frame2d.withXDirection
        (Direction2d.fromAngle (degrees 30))
        (Point2d.fromCoordinates ( 2, 3 ))


Frame2d.yDirection frame
--> Direction2d.fromAngle (degrees 120)
withYDirection : Direction2d -> Point2d -> Frame2d

Construct a frame with the given Y axis direction, having the given origin point. The X axis direction will be constructed by rotating the given X direction 90 degrees clockwise:

frame =
    Frame2d.withYDirection
        (Direction2d.fromAngle (degrees 30))
        (Point2d.fromCoordinates ( 2, 3 ))


Frame2d.yDirection frame
--> Direction2d.fromAngle (degrees -60)
{ originPoint : Point2d
, xDirection : Direction2d
, yDirection : Direction2d
}
-> Frame2d

Construct a frame directly from its origin point and X and Y directions:

frame =
    Frame2d.unsafe
        { originPoint =
            Point2d.fromCoordinates ( 2, 3 )
        , xDirection =
            Direction2d.fromAngle (degrees 45)
        , yDirection =
            Direction2d.fromAngle (degrees 135)
        }

In this case you must be careful to ensure that the X and Y directions are perpendicular. To construct pairs of perpendicular directions, Direction2d.orthonormalize or Direction2d.orthogonalize may be useful.

Properties

originPoint : Frame2d -> Point2d

Get the origin point of a given frame.

Frame2d.originPoint Frame2d.atOrigin
--> Point2d.origin
xDirection : Frame2d -> Direction2d

Get the X direction of a given frame.

Frame2d.xDirection Frame2d.atOrigin
--> Direction2d.x
yDirection : Frame2d -> Direction2d

Get the Y direction of a given frame.

Frame2d.yDirection Frame2d.atOrigin
--> Direction2d.y
isRightHanded : Frame2d -> Bool

Check if a frame is right-handed.

Frame2d.isRightHanded Frame2d.atOrigin
--> True


Frame2d.isRightHanded
    (Frame2d.reverseX Frame2d.atOrigin)
--> False

All predefined frames are right-handed, and most operations on frames preserve handedness, so about the only ways to end up with a left-handed frame are by constructing one explicitly with unsafe or by mirroring a right-handed frame.

xAxis : Frame2d -> Axis2d

Get the X axis of a given frame (the axis formed from the frame's origin point and X direction).

Frame2d.xAxis Frame2d.atOrigin
--> Axis2d.x
yAxis : Frame2d -> Axis2d

Get the Y axis of a given frame (the axis formed from the frame's origin point and Y direction).

Frame2d.yAxis Frame2d.atOrigin
--> Axis2d.y

Transformations

reverseX : Frame2d -> Frame2d

Reverse the X direction of a frame, leaving its Y direction and origin point the same.

point =
    Point2d.fromCoordinates ( 2, 3 )


frame =
    Frame2d.atPoint point |> Frame2d.reverseX


Frame2d.originPoint frame
--> point


Frame2d.xDirection frame
--> Direction2d.negativeX


Frame2d.yDirection frame
--> Direction2d.y

Note that this will switch the handedness of the frame.

reverseY : Frame2d -> Frame2d

Reverse the Y direction of a frame, leaving its X direction and origin point the same.

point =
    Point2d.fromCoordinates ( 2, 3 )


frame =
    Frame2d.atPoint point |> Frame2d.reverseY


Frame2d.originPoint frame
--> point


Frame2d.xDirection frame
--> Direction2d.x


Frame2d.yDirection frame
--> Direction2d.negativeY

Note that this will switch the handedness of the frame.

moveTo : Point2d -> Frame2d -> Frame2d

Move a frame so that it has the given origin point.

point =
    Point2d.fromCoordinates ( 1, 1 )


Frame2d.atOrigin |> Frame2d.moveTo point
--> Frame2d.atPoint point
rotateBy : Float -> Frame2d -> Frame2d

Rotate a frame counterclockwise by a given angle around the frame's own origin point. The resulting frame will have the same origin point, and its X and Y directions will be rotated by the given angle.

rotatedFrame =
    Frame2d.rotateBy (degrees 30) Frame2d.atOrigin


Frame2d.xDirection rotatedFrame
--> Direction2d.fromAngle (degrees 30)


Frame2d.yDirection rotatedFrame
--> Direction2d.fromAngle (degrees 120)
rotateAround : Point2d -> Float -> Frame2d -> Frame2d

Rotate a frame counterclockwise around a given point by a given angle. The frame's origin point will be rotated around the given point by the given angle, and its X and Y basis directions will be rotated by the given angle.

rotatedFrame =
    Frame2d.atPoint (Point2d.fromCoordinates ( 1, 1 ))
        |> Frame2d.rotateAround Point2d.origin
            (degrees 45)


Frame2d.originPoint rotatedFrame
--> Point2d.fromCoordinates ( 0, 1.4142 )


Frame2d.xDirection rotatedFrame
--> Direction2d.fromAngle (degrees 45)


Frame2d.yDirection rotatedFrame
--> Direction2d.fromAngle (degrees 135)
translateBy : Vector2d -> Frame2d -> Frame2d

Translate a frame by a given displacement.

frame =
    Frame2d.atPoint (Point2d.fromCoordinates ( 2, 3 ))


displacement =
    Vector2d.fromComponents ( 1, 1 )


Frame2d.translateBy displacement frame
--> Frame2d.atPoint (Point2d.fromCoordinates ( 3, 4 ))
translateIn : Direction2d -> Float -> Frame2d -> Frame2d

Translate a frame in a given direction by a given distance;

Frame2d.translateIn direction distance

is equivalent to

Frame2d.translateBy
    (Vector2d.withLength distance direction)
translateAlongOwn : (Frame2d -> Axis2d) -> Float -> Frame2d -> Frame2d

Translate a frame along one of its own axes by a given distance.

The first argument is a function that returns the axis to translate along, given the current frame. The majority of the time this argument will be either Frame2d.xAxis or Frame2d.yAxis. The second argument is the distance to translate along the given axis.

This function is convenient when constructing frames via a series of transformations. For example,

frame =
    Frame2d.atPoint (Point2d.fromCoordinates ( 2, 0 ))
        |> Frame2d.rotateBy (degrees 45)
        |> Frame2d.translateAlongOwn Frame2d.xAxis 2

means "construct a frame at the point (2, 0), rotate it around its own origin point by 45 degrees, then translate it along its own X axis by 2 units", resulting in

Frame2d.originPoint frame
--> Point2d.fromCoordinates ( 3.4142, 1.4142 )


Frame2d.xDirection frame
--> Direction2d.fromAngle (degrees 45)


Frame2d.yDirection frame
--> Direction2d.fromAngle (degrees 135)
mirrorAcross : Axis2d -> Frame2d -> Frame2d

Mirror a frame across an axis.

frame =
    Frame2d.atPoint (Point2d.fromCoordinates ( 2, 3 ))


mirroredFrame =
    Frame2d.mirrorAcross Axis2d.x frame


Frame2d.originPoint mirroredFrame
--> Point2d.fromCoordinates ( 2, -3 )


Frame2d.xDirection mirroredFrame
--> Direction2d.x


Frame2d.yDirection mirroredFrame
--> Direction2d.negativeY

Note that this will switch the handedness of the frame.

Coordinate conversions

relativeTo : Frame2d -> Frame2d -> Frame2d

Take two frames defined in global coordinates, and return the second one expressed in local coordinates relative to the first.

placeIn : Frame2d -> Frame2d -> Frame2d

Take one frame defined in global coordinates and a second frame defined in local coordinates relative to the first frame, and return the second frame expressed in global coordinates.