This is an alternative site for discovering Elm packages. You may be looking for the official Elm package site instead.

# Direction3d A `Direction3d` represents a direction like 'up' or 'north' or 'forwards'. They are represented using X, Y and Z components, and can be converted to vectors if necessary, but should be thought of as conceptually different. Directions have several uses, such as:

• Constructing a vector from a length and direction
• Determining the component of a vector in a particular direction (for example, finding the component of velocity in the up direction to get vertical speed)
• Determining the angle between two directions
• Defining the orientation of an axis, plane or reference frame
type alias Direction3d = Types.Direction3d

# Constants

x : Direction3d
y : Direction3d
z : Direction3d
positiveX : Direction3d
negativeX : Direction3d
positiveY : Direction3d
negativeY : Direction3d
positiveZ : Direction3d
negativeZ : Direction3d

# Constructors

from : Point3d -> Point3d -> Maybe Direction3d
on : SketchPlane3d -> Direction2d -> Direction3d
fromAzimuthAndElevation : Float -> Float -> Direction3d
perpendicularTo : Direction3d -> Direction3d
perpendicularBasis : Direction3d -> ( Direction3d, Direction3d )
orthonormalize : Vector3d -> Vector3d -> Vector3d -> Maybe ( Direction3d, Direction3d, Direction3d )
orthogonalize : Direction3d -> Direction3d -> Direction3d -> Maybe ( Direction3d, Direction3d, Direction3d )
unsafe : ( Float, Float, Float ) -> Direction3d

# Properties

components : Direction3d -> ( Float, Float, Float )
xComponent : Direction3d -> Float
yComponent : Direction3d -> Float
zComponent : Direction3d -> Float
azimuth : Direction3d -> Float
elevation : Direction3d -> Float

# Comparison

equalWithin : Float -> Direction3d -> Direction3d -> Bool

# Measurement

componentIn : Direction3d -> Direction3d -> Float
angleFrom : Direction3d -> Direction3d -> Float

# Conversion

toVector : Direction3d -> Vector3d

# Transformations

reverse : Direction3d -> Direction3d
rotateAround : Axis3d -> Float -> Direction3d -> Direction3d
mirrorAcross : Plane3d -> Direction3d -> Direction3d
projectOnto : Plane3d -> Direction3d -> Maybe Direction3d

# Coordinate conversions

relativeTo : Frame3d -> Direction3d -> Direction3d
placeIn : Frame3d -> Direction3d -> Direction3d
projectInto : SketchPlane3d -> Direction3d -> Maybe Direction2d
``````--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-- This Source Code Form is subject to the terms of the Mozilla Public        --
-- License, v. 2.0. If a copy of the MPL was not distributed with this file,  --
-- you can obtain one at http://mozilla.org/MPL/2.0/.                         --
--                                                                            --
-- Copyright 2016 by Ian Mackenzie                                            --
-- ian.e.mackenzie@gmail.com                                                  --
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------

module Direction3d
exposing
( Direction3d
, angleFrom
, azimuth
, componentIn
, components
, elevation
, equalWithin
, from
, fromAzimuthAndElevation
, mirrorAcross
, negativeX
, negativeY
, negativeZ
, on
, orthogonalize
, orthonormalize
, perpendicularBasis
, perpendicularTo
, placeIn
, positiveX
, positiveY
, positiveZ
, projectInto
, projectOnto
, relativeTo
, reverse
, rotateAround
, toVector
, unsafe
, x
, xComponent
, y
, yComponent
, z
, zComponent
)

{-| <img src="https://ianmackenzie.github.io/elm-geometry/1.0.0/Direction3d/icon.svg" alt="Direction3d" width="160">

A `Direction3d` represents a direction like 'up' or 'north' or 'forwards'. They
are represented using X, Y and Z components, and can be converted to vectors if
necessary, but should be thought of as conceptually different. Directions have
several uses, such as:

- Constructing a vector from a length and direction
- Determining the component of a vector in a particular direction (for
example, finding the component of velocity in the up direction to get
vertical speed)
- Determining the angle between two directions
- Defining the orientation of an axis, plane or reference frame

@docs Direction3d

# Constants

@docs x, y, z, positiveX, negativeX, positiveY, negativeY, positiveZ, negativeZ

# Constructors

@docs from, on, fromAzimuthAndElevation, perpendicularTo, perpendicularBasis, orthonormalize, orthogonalize, unsafe

# Properties

@docs components, xComponent, yComponent, zComponent, azimuth, elevation

# Comparison

@docs equalWithin

# Measurement

@docs componentIn, angleFrom

# Conversion

@docs toVector

# Transformations

@docs reverse, rotateAround, mirrorAcross, projectOnto

# Coordinate conversions

@docs relativeTo, placeIn, projectInto

-}

import Bootstrap.SketchPlane3d as SketchPlane3d
import Direction2d exposing (Direction2d)
import Geometry.Types as Types exposing (Axis3d, Frame3d, Plane3d, Point3d, SketchPlane3d)
import Vector2d exposing (Vector2d)
import Vector3d exposing (Vector3d)

toDirection : Vector3d -> Direction3d
toDirection vector =
unsafe (Vector3d.components vector)

{-| -}
type alias Direction3d =
Types.Direction3d

{-| -}
x : Direction3d
x =
unsafe ( 1, 0, 0 )

{-| -}
y : Direction3d
y =
unsafe ( 0, 1, 0 )

{-| -}
z : Direction3d
z =
unsafe ( 0, 0, 1 )

{-| -}
positiveX : Direction3d
positiveX =
unsafe ( 1, 0, 0 )

{-| -}
negativeX : Direction3d
negativeX =
unsafe ( -1, 0, 0 )

{-| -}
positiveY : Direction3d
positiveY =
unsafe ( 0, 1, 0 )

{-| -}
negativeY : Direction3d
negativeY =
unsafe ( 0, -1, 0 )

{-| -}
positiveZ : Direction3d
positiveZ =
unsafe ( 0, 0, 1 )

{-| -}
negativeZ : Direction3d
negativeZ =
unsafe ( 0, 0, -1 )

{-| -}
unsafe : ( Float, Float, Float ) -> Direction3d
unsafe =
Types.Direction3d

{-| -}
on : SketchPlane3d -> Direction2d -> Direction3d
on sketchPlane direction2d =
let
( dx, dy ) =
Direction2d.components direction2d

( ux, uy, uz ) =
components (SketchPlane3d.xDirection sketchPlane)

( vx, vy, vz ) =
components (SketchPlane3d.yDirection sketchPlane)
in
unsafe
( dx * ux + dy * vx
, dx * uy + dy * vy
, dx * uz + dy * vz
)

{-| -}
fromAzimuthAndElevation : Float -> Float -> Direction3d
fromAzimuthAndElevation azimuth_ elevation_ =
let
cosElevation =
cos elevation_
in
unsafe
( cosElevation * cos azimuth_
, cosElevation * sin azimuth_
, sin elevation_
)

{-| -}
from : Point3d -> Point3d -> Maybe Direction3d
from firstPoint secondPoint =
Vector3d.direction (Vector3d.from firstPoint secondPoint)

{-| -}
perpendicularTo : Direction3d -> Direction3d
perpendicularTo direction =
let
perpendicularVector =
Vector3d.perpendicularTo (toVector direction)

length =
Vector3d.length perpendicularVector

normalizedVector =
Vector3d.scaleBy (1 / length) perpendicularVector
in
toDirection normalizedVector

{-| -}
perpendicularBasis : Direction3d -> ( Direction3d, Direction3d )
perpendicularBasis direction =
let
xDirection =
perpendicularTo direction

yDirection =
Vector3d.crossProduct (toVector direction) (toVector xDirection)
|> toDirection
in
( xDirection, yDirection )

{-| -}
orthonormalize : Vector3d -> Vector3d -> Vector3d -> Maybe ( Direction3d, Direction3d, Direction3d )
orthonormalize xVector xyVector xyzVector =
Vector3d.direction xVector
|> Maybe.andThen
(\xDirection ->
let
yVector =
Vector3d.crossProduct
(Vector3d.crossProduct xVector xyVector)
xVector
in
Vector3d.direction yVector
|> Maybe.andThen
(\yDirection ->
let
rightHandedZVector =
Vector3d.crossProduct xVector yVector

dotProduct =
Vector3d.dotProduct
xyzVector
rightHandedZVector

zVector =
if dotProduct > 0 then
rightHandedZVector
else if dotProduct < 0 then
Vector3d.reverse rightHandedZVector
else
Vector3d.zero
in
Vector3d.direction zVector
|> Maybe.map
(\zDirection ->
( xDirection
, yDirection
, zDirection
)
)
)
)

{-| -}
orthogonalize : Direction3d -> Direction3d -> Direction3d -> Maybe ( Direction3d, Direction3d, Direction3d )
orthogonalize xDirection yDirection zDirection =
orthonormalize
(toVector xDirection)
(toVector yDirection)
(toVector zDirection)

{-| -}
components : Direction3d -> ( Float, Float, Float )
components (Types.Direction3d components_) =
components_

{-| -}
xComponent : Direction3d -> Float
xComponent (Types.Direction3d ( xComponent_, _, _ )) =
xComponent_

{-| -}
yComponent : Direction3d -> Float
yComponent (Types.Direction3d ( _, yComponent_, _ )) =
yComponent_

{-| -}
zComponent : Direction3d -> Float
zComponent (Types.Direction3d ( _, _, zComponent_ )) =
zComponent_

{-| -}
componentIn : Direction3d -> Direction3d -> Float
componentIn firstDirection secondDirection =
Vector3d.componentIn firstDirection (toVector secondDirection)

{-| -}
azimuth : Direction3d -> Float
azimuth direction =
atan2 (yComponent direction) (xComponent direction)

{-| -}
elevation : Direction3d -> Float
elevation direction =
asin (zComponent direction)

{-| -}
equalWithin : Float -> Direction3d -> Direction3d -> Bool
equalWithin angle firstDirection secondDirection =
angleFrom firstDirection secondDirection <= angle

{-| -}
toVector : Direction3d -> Vector3d
toVector direction =
Vector3d.fromComponents (components direction)

{-| -}
angleFrom : Direction3d -> Direction3d -> Float
angleFrom firstDirection secondDirection =
let
( x1, y1, z1 ) =
components firstDirection

( x2, y2, z2 ) =
components secondDirection

relativeX =
x1 * x2 + y1 * y2 + z1 * z2

cx =
y1 * z2 - z1 * y2

cy =
z1 * x2 - x1 * z2

cz =
x1 * y2 - y1 * x2

relativeY =
sqrt (cx * cx + cy * cy + cz * cz)
in
atan2 relativeY relativeX

{-| -}
reverse : Direction3d -> Direction3d
reverse direction =
let
( dx, dy, dz ) =
components direction
in
unsafe ( -dx, -dy, -dz )

{-| -}
rotateAround : Axis3d -> Float -> Direction3d -> Direction3d
rotateAround axis angle direction =
toVector direction |> Vector3d.rotateAround axis angle |> toDirection

{-| -}
mirrorAcross : Plane3d -> Direction3d -> Direction3d
mirrorAcross plane direction =
toVector direction |> Vector3d.mirrorAcross plane |> toDirection

{-| -}
projectOnto : Plane3d -> Direction3d -> Maybe Direction3d
projectOnto plane direction =
toVector direction |> Vector3d.projectOnto plane |> Vector3d.direction

{-| -}
relativeTo : Frame3d -> Direction3d -> Direction3d
relativeTo frame direction =
toVector direction |> Vector3d.relativeTo frame |> toDirection

{-| -}
placeIn : Frame3d -> Direction3d -> Direction3d
placeIn frame direction =
toVector direction |> Vector3d.placeIn frame |> toDirection

{-| -}
projectInto : SketchPlane3d -> Direction3d -> Maybe Direction2d
projectInto sketchPlane direction =
toVector direction |> Vector3d.projectInto sketchPlane |> Vector2d.direction
```
```