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:
Geometry.Types.Direction3d coordinates
x : Direction3d coordinates
Synonym for Direction3d.positiveX
.
y : Direction3d coordinates
Synonym for Direction3d.positiveY
.
z : Direction3d coordinates
Synonym for Direction3d.positiveZ
.
positiveX : Direction3d coordinates
The positive X direction.
negativeX : Direction3d coordinates
The negative X direction.
positiveY : Direction3d coordinates
The positive Y direction.
negativeY : Direction3d coordinates
The negative Y direction.
positiveZ : Direction3d coordinates
The positive Z direction.
negativeZ : Direction3d coordinates
The negative Z direction.
from : Geometry.Types.Point3d units coordinates -> Geometry.Types.Point3d units coordinates -> Maybe (Direction3d coordinates)
Attempt to construct the direction from the first given point to the second.
If the two points are coincident, returns Nothing
.
point =
Point3d.meters 1 0 1
Direction3d.from Point3d.origin point
--> Just (Direction3d.xz (Angle.degrees 45))
Direction3d.from point Point3d.origin
--> Just (Direction3d.xz (Angle.degrees -135))
Direction3d.from point point
--> Nothing
xy : Angle -> Direction3d coordinates
Construct a direction in the XY plane given an angle measured from positive X towards positive Y:
Direction3d.xy (Angle.degrees 0)
--> Direction3d.positiveX
Direction3d.xy (Angle.degrees 90)
--> Direction3d.positiveY
Direction3d.xy (Angle.degrees 180)
--> Direction3d.negativeX
yx : Angle -> Direction3d coordinates
Construct a direction in the XY plane given an angle measured from positive Y towards positive X:
Direction3d.yx (Angle.degrees 0)
--> Direction3d.positiveY
Direction3d.yx (Angle.degrees 90)
--> Direction3d.positiveX
Direction3d.yx (Angle.degrees -90)
--> Direction3d.negativeX
yz : Angle -> Direction3d coordinates
Construct a direction in the YZ plane given an angle measured from positive Y towards positive Z.
zy : Angle -> Direction3d coordinates
Construct a direction in the YZ plane given an angle measured from positive Z towards positive Y.
zx : Angle -> Direction3d coordinates
Construct a direction in the XZ plane given an angle measured from positive Z towards positive X.
xz : Angle -> Direction3d coordinates
Construct a direction in the XZ plane given an angle measured from positive X towards positive Z.
on : Geometry.Types.SketchPlane3d units coordinates3d { defines : coordinates2d } -> Direction2d coordinates2d -> Direction3d coordinates3d
Construct a 3D direction lying on a sketch plane by providing a 2D
direction specified in XY coordinates within the sketch plane. This is a
generalized version of Direction3d.xy
, Direction3d.yz
etc.; for example,
Direction3d.xy (Angle.degrees 45)
is equivalent to
Direction3d.on SketchPlane3d.xy (Direction2d.degrees 45)
xyZ : Angle -> Angle -> Direction3d coordinates
Construct a direction given:
See
here
for an illustration of these two angles (except that this function measures
azimuth from positive X towards positive Y, not negative Y towards positive
X). Note that Direction3d.xyZ
is a generalized version of Direction3d.xy
;
Direction3d.xy angle
is equivalent to
Direction3d.xyZ angle (Angle.degrees 0)
yzX : Angle -> Angle -> Direction3d coordinates
Construct a direction given:
This is generally not as useful as Direction3d.xyZ
or Direction3d.zxY
.
zxY : Angle -> Angle -> Direction3d coordinates
Construct a direction given:
This may be useful if you like to use positive Y as your global up vector.
fromAzimuthInAndElevationFrom : Geometry.Types.SketchPlane3d units coordinates3d defines -> Angle -> Angle -> Direction3d coordinates3d
Construct a direction given:
This is a generalized version of Direction3d.xyZ
, Direction3d.yzX
and
Direction3d.zxY
; for example,
Direction3d.xyZ azimuth elevation
is equivalent to
Direction3d.fromAzimuthInAndElevationFrom
SketchPlane3d.xy
azimuth
elevation
perpendicularTo : Direction3d coordinates -> Direction3d coordinates
Construct an arbitrary direction perpendicular to the given direction. The exact resulting direction is not specified, but it is guaranteed to be perpendicular to the given direction.
Direction3d.perpendicularTo Direction3d.x
--> Direction3d.negativeZ
Direction3d.perpendicularTo Direction3d.y
--> Direction3d.positiveZ
direction =
Direction3d.xz (Angle.degrees 60)
Direction3d.perpendicularTo direction
--> Direction3d.xz (Angle.degrees -30)
perpendicularBasis : Direction3d coordinates -> ( Direction3d coordinates, Direction3d coordinates )
Construct a pair of directions that are perpendicular to each other and both perpendicular to the given direction.
The given direction and the two returned directions will form a
right-handed
system (that is, a right-handed Frame3d
could be constructed by using the
given direction as the X direction and the two returned directions as the Y and
Z directions, or the given direction as the Z direction and the two returned
directions as the X and Y directions).
Direction3d.perpendicularBasis Direction3d.x
--> ( Direction3d.negativeZ
--> , Direction3d.positiveY
--> )
Direction3d.perpendicularBasis Direction3d.y
--> ( Direction3d.positiveZ
--> , Direction3d.positiveX
--> )
orthonormalize : Vector3d units1 coordinates -> Vector3d units2 coordinates -> Vector3d units3 coordinates -> Maybe ( Direction3d coordinates, Direction3d coordinates, Direction3d coordinates )
Attempt to form a set of three mutually perpendicular directions from the three given vectors by performing Gram-Schmidt normalization:
If any of the given vectors are zero, any two of them are parallel, or the three
are coplanar, returns Nothing
.
Direction3d.orthonormalize
(Vector3d.meters 3 3 0)
(Vector3d.meters 0 2 0)
(Vector3d.meters 1 2 3)
--> Just
--> ( Direction3d.xy (Angle.degrees 45)
--> , Direction3d.xy (Angle.degrees 135)
--> , Direction3d.z
--> )
-- Three vectors in the XY plane:
Direction3d.orthonormalize
(Vector3d.meters 2 0 0)
(Vector3d.meters 3 1 0)
(Vector3d.meters 4 2 0)
--> Nothing
orthogonalize : Direction3d coordinates -> Direction3d coordinates -> Direction3d coordinates -> Maybe ( Direction3d coordinates, Direction3d coordinates, Direction3d coordinates )
Attempt to form a set of three mutually perpendicular directions from the three given directions;
Direction3d.orthogonalize
xDirection
yDirection
zDirection
is equivalent to
Direction3d.orthonormalize
(Direction3d.toVector xDirection)
(Direction3d.toVector yDirection)
(Direction3d.toVector zDirection)
toVector : Direction3d coordinates -> Vector3d Quantity.Unitless coordinates
Convert a direction to a unitless vector of length 1.
Direction3d.toVector Direction3d.y
--> Vector3d.unitless 0 1 0
components : Direction3d coordinates -> ( Basics.Float, Basics.Float, Basics.Float )
Get the X, Y and Z components of a direction as a tuple.
Direction3d.yz (Angle.degrees 135)
|> Direction3d.components
--> ( 0, -0.7071, 0.7071 )
xComponent : Direction3d coordinates -> Basics.Float
Get the X component of a direction.
Direction3d.xComponent Direction3d.x
--> 1
Direction3d.xComponent Direction3d.y
--> 0
yComponent : Direction3d coordinates -> Basics.Float
Get the Y component of a direction.
Direction3d.yComponent Direction3d.y
--> 1
Direction3d.yComponent Direction3d.z
--> 0
zComponent : Direction3d coordinates -> Basics.Float
Get the Z component of a direction.
Direction3d.zComponent Direction3d.z
--> 1
Direction3d.zComponent Direction3d.x
--> 0
componentIn : Direction3d coordinates -> Direction3d coordinates -> Basics.Float
Find the component of one direction in another direction. This is equal to the cosine of the angle between the directions, or equivalently the dot product of the two directions converted to unit vectors.
direction =
Direction3d.xz (Angle.degrees 60)
Direction3d.componentIn Direction3d.x direction
--> 0.5
Direction3d.componentIn Direction3d.z direction
--> 0.866
Direction3d.componentIn direction direction
--> 1
direction
|> Direction3d.componentIn
(Direction3d.reverse direction)
--> -1
This is more general and flexible than using xComponent
, yComponent
or
zComponent
, all of which can be expressed in terms of componentIn
; for
example,
Direction3d.zComponent direction
is equivalent to
Direction3d.componentIn Direction3d.z direction
angleFrom : Direction3d coordinates -> Direction3d coordinates -> Angle
Find the angle from one direction to another. The result will be in the range 0 to 180 degrees
Direction3d.angleFrom Direction3d.x Direction3d.x
--> Angle.degrees 0
Direction3d.angleFrom Direction3d.x Direction3d.z
--> Angle.degrees 90
Direction3d.angleFrom
Direction3d.y
Direction3d.negativeY
--> Angle.degrees 180
azimuthIn : Geometry.Types.SketchPlane3d units coordinates3d { defines : coordinates2d } -> Direction3d coordinates3d -> Angle
Get the azimuth of a direction in a given sketch plane (the angle of that direction projected into the sketch plane), measured from its X axis towards its Y axis (counterclockwise around the sketch plane's normal axis). The result will be in the range -180 degrees to 180 degrees.
Direction3d.x
|> Direction3d.azimuthIn SketchPlane3d.xy
--> Angle.degrees 0
Direction3d.y
|> Direction3d.azimuthIn SketchPlane3d.xy
--> Angle.degrees 90
Direction3d.negativeY
|> Direction3d.azimuthIn SketchPlane3d.xy
--> Angle.degrees -90
Direction3d.negativeX
|> Direction3d.azimuthIn SketchPlane3d.xy
--> Angle.degrees 180
Vertical directions are considered to have an azimuth of zero:
Direction3d.z |> Direction3d.azimuthIn SketchPlane3d.xy
--> Angle.degrees 0
elevationFrom : Geometry.Types.SketchPlane3d units coordinates3d defines -> Direction3d coordinates3d -> Angle
Get the elevation angle of a direction from a given sketch plane (the angle between the direction and the sketch plane, in the direction of the sketch plane's normal). Directions in (coplanar with) the sketch plane have an elevation angle of zero. The result will be in the range -90 degrees to 90 degrees.
Direction3d.x
|> Direction3d.elevationFrom SketchPlane3d.xy
--> Angle.degrees 0
Direction3d.y
|> Direction3d.elevationFrom SketchPlane3d.xy
--> Angle.degrees 0
Direction3d.z
|> Direction3d.elevationFrom SketchPlane3d.xy
--> Angle.degrees 90
Direction3d.negativeZ
|> Direction3d.elevationFrom SketchPlane3d.xy
--> Angle.degrees -90
equalWithin : Angle -> Direction3d coordinates -> Direction3d coordinates -> Basics.Bool
Compare two directions within an angular tolerance. Returns true if the angle between the two given directions is less than the given tolerance.
rotatedDirection =
Direction3d.x
|> Direction3d.rotateAround Direction3d.z
(Angle.degrees 2)
Direction3d.equalWithin (Angle.degrees 5)
Direction3d.x
rotatedDirection
--> True
Direction3d.equalWithin (Angle.degrees 1)
Direction3d.x
rotatedDirection
--> False
reverse : Direction3d coordinates -> Direction3d coordinates
Reverse a direction.
rotateAround : Direction3d coordinates -> Angle -> Direction3d coordinates -> Direction3d coordinates
Rotate a direction around another direction by a given angle.
Direction3d.y
|> Direction3d.rotateAround Direction3d.x
(Angle.degrees 90)
--> Direction3d.z
mirrorAcross : Geometry.Types.Plane3d units coordinates -> Direction3d coordinates -> Direction3d coordinates
Mirror a direction across a plane.
direction =
Direction3d.xyZ (Angle.degrees 30)
(Angle.degrees 60)
Direction3d.mirrorAcross Plane3d.xy direction
--> Direction3d.xyZ (Angle.degrees 30)
--> (Angle.degrees -60)
Note that only the normal direction of the plane affects the result, not the position of its origin point, since directions are position-independent:
Direction3d.mirrorAcross Plane3d.yz direction
--> Direction3d.xyZ (Angle.degrees 150)
--> (Angle.degrees 60)
offsetPlane =
Plane3d.offsetBy 10 Plane3d.yz
Direction3d.mirrorAcross offsetPlane direction
--> Direction3d.xyZ (Angle.degrees 150)
--> (Angle.degrees 60)
projectOnto : Geometry.Types.Plane3d units coordinates -> Direction3d coordinates -> Maybe (Direction3d coordinates)
Find the orthographic projection
of a direction onto a plane (renormalized to have unit length). If the given
direction is exactly perpendicular to the given plane, returns Nothing
.
direction =
Direction3d.xyZ (Angle.degrees -60)
(Angle.degrees 0)
Direction3d.projectOnto Plane3d.xy direction
--> Just direction
Direction3d.projectOnto Plane3d.xz direction
--> Just Direction3d.x
Direction3d.projectOnto Plane3d.yz direction
--> Just Direction3d.negativeY
Direction3d.projectOnto Plane3d.xy Direction3d.z
--> Nothing
Like other transformations, coordinate transformations of directions depend only on the orientations of the relevant frames, not their positions.
For the examples, assume the following definition of a local coordinate frame, one that is rotated 30 degrees counterclockwise around the Z axis from the global XYZ frame:
rotatedFrame =
Frame3d.atOrigin
|> Frame3d.rotateAround Axis3d.z (Angle.degrees 30)
relativeTo : Geometry.Types.Frame3d units globalCoordinates { defines : localCoordinates } -> Direction3d globalCoordinates -> Direction3d localCoordinates
Take a direction defined in global coordinates, and return it expressed in local coordinates relative to a given reference frame.
Direction3d.relativeTo rotatedFrame Direction3d.x
--> Direction3d.xy (Angle.degrees -30)
Direction3d.relativeTo rotatedFrame Direction3d.y
--> Direction3d.xy (Angle.degrees 60)
Direction3d.relativeTo rotatedFrame Direction3d.z
--> Direction3d.z
placeIn : Geometry.Types.Frame3d units globalCoordinates { defines : localCoordinates } -> Direction3d localCoordinates -> Direction3d globalCoordinates
Take a direction defined in local coordinates relative to a given reference frame, and return that direction expressed in global coordinates.
Direction3d.placeIn rotatedFrame Direction3d.x
--> Direction3d.xy (Angle.degrees 30)
Direction3d.placeIn rotatedFrame Direction3d.y
--> Direction3d.xy (Angle.degrees 120)
Direction3d.placeIn rotatedFrame Direction3d.z
--> Direction3d.z
projectInto : Geometry.Types.SketchPlane3d units coordinates3d { defines : coordinates2d } -> Direction3d coordinates3d -> Maybe (Direction2d coordinates2d)
Project a direction into a given sketch plane. Conceptually, this finds the orthographic projection of the direction onto the plane, re-normalizes it to have unit length, and then expresses the projected direction in 2D sketch coordinates.
This is only possible if the direction is not perpendicular to the sketch
plane; if it is perpendicular, Nothing
is returned.
direction =
Direction3d.xy (Angle.degrees -60)
Direction3d.projectInto SketchPlane3d.xy direction
--> Just (Direction2d.degrees -60)
Direction3d.projectInto SketchPlane3d.xz direction
--> Just Direction2d.x
Direction3d.projectInto SketchPlane3d.yz direction
--> Just Direction2d.negativeX
Direction3d.projectInto SketchPlane3d.xy Direction3d.z
--> Nothing
random : Random.Generator (Direction3d coordinates)
A random generator for 3D directions.
unsafe : { x : Basics.Float, y : Basics.Float, z : Basics.Float } -> Direction3d coordinates
Construct a direction directly from its X, Y and Z components. Note that you must ensure that the sum of the squares of the given components is exactly one:
Direction3d.unsafe { x = 1, y = 0, z = 0 }
Direction3d.unsafe { x = 0, y = -1, z = 0 }
Direction3d.unsafe { x = 0.6, y = 0, z = 0.8 }
are all valid but
Direction3d.unsafe { x = 2, y = 0, z = 0 }
Direction3d.unsafe { x = 1, y = 1, z = 1 }
are not. Instead of using Direction3d.unsafe
, it may be easier to use
constructors like Direction3d.on
or Direction3d.xyZ
(which will always
result in a valid direction), or start with existing directions and transform
them as necessary.
unwrap : Direction3d coordinates -> { x : Basics.Float, y : Basics.Float, z : Basics.Float }
Extract the X, Y and Z components of a direction as a record.