A Vector3d represents a quantity such as a displacement or velocity in 3D, and
is defined by its X, Y and Z components. This module contains a variety of
vector-related functionality, such as
Note that unlike in many other geometry packages where vectors are used as a
general-purpose data type, OpenSolid has separate data types for vectors,
directions and points. In most code it is actually more common to use Point3d
and Direction3d than Vector3d, and much code can avoid working directly with
Vector3d values at all!
The simplest way to create a Vector3d is by passing a tuple of X, Y and Z
components to the Vector3d constructor, for example
vector =
Vector3d ( 2, 1, 3 )Although there are no predefined constants for
Vector3d ( 1, 0, 0 ),
Vector3d ( 0, 1, 0 ) and
Vector3d ( 0, 0, 1 ), in most cases you
will actually want their Direction3d versions Direction3d.x,
Direction3d.y and Direction3d.z.
Construct a vector in the given direction with the given length.
Vector3d.in_ Direction3d.y 5
--> Vector3d ( 0, 5, 0 )Construct an arbitrary vector perpendicular to the given vector. The exact length and direction of the resulting vector are not specified, but it is guaranteed to be perpendicular to the given vector and non-zero (unless the given vector is itself zero).
Vector3d.perpendicularTo (Vector3d ( 3, 0, 0 ))
--> Vector3d ( 0, 0, -3 )
Vector3d.perpendicularTo (Vector3d ( 1, 2, 3 ))
--> Vector3d ( 0, -3, 2 )
Vector3d.perpendicularTo Vector3d.zero
--> Vector3d.zeroConstruct a vector by interpolating from the first given vector to the second, based on a parameter that ranges from zero to one.
startVector =
Vector3d ( 1, 2, 4 )
endVector =
Vector3d ( 1, 2, 8 )
Vector3d.interpolateFrom startVector endVector 0.25
--> Vector3d ( 1, 2, 5 )Partial application may be useful:
interpolatedVector : Float -> Vector3d
interpolatedVector =
Vector3d.interpolateFrom startVector endVector
List.map interpolatedVector [ 0, 0.5, 1 ]
--> [ Vector3d ( 1, 2, 4 )
--> , Vector3d ( 1, 2, 6 )
--> , Vector3d ( 1, 2, 8 )
--> ]You can pass values less than zero or greater than one to extrapolate:
interpolatedVector -0.5
--> Vector3d ( 1, 2, 2 )
interpolatedVector 1.25
--> Vector3d ( 1, 2, 9 )Extract the components of a vector.
Vector3d.components (Vector2d ( 2, 3, 4 ))
--> ( 2, 3, 4 )This combined with Elm's built-in tuple destructuring provides a convenient way to extract the X, Y and Z components of a vector in one line of code:
( x, y, z ) =
Vector3d.components vectorGet the X component of a vector.
Vector3d.xComponent (Vector3d ( 1, 2, 3 ))
--> 1Get the Y component of a vector.
Vector3d.yComponent (Vector3d ( 1, 2, 3 ))
--> 2Get the Z component of a vector.
Vector3d.zComponent (Vector3d ( 1, 2, 3 ))
--> 3Find the component of a vector in an arbitrary direction, for example
verticalSpeed =
Vector3d.componentIn upDirection velocityThis is more general and flexible than using xComponent, yComponent or
zComponent, all of which can be expressed in terms of componentIn; for
example,
Vector3d.zComponent vectoris equivalent to
Vector3d.componentIn Direction3d.z vectorCompare two vectors within a tolerance. Returns true if the difference between the two given vectors has magnitude less than the given tolerance.
firstVector =
Vector3d ( 2, 1, 3 )
secondVector =
Vector3d ( 2.0002, 0.9999, 3.0001 )
Vector3d.equalWithin 1e-3 firstVector secondVector
--> True
Vector3d.equalWithin 1e-6 firstVector secondVector
--> FalseGet the length (magnitude) of a vector.
Vector3d.length (Vector3d ( 2, 1, 2 ))
--> 3Get the squared length of a vector. squaredLength is slightly faster than
length, so for example
Vector3d.squaredLength vector > tolerance * toleranceis equivalent to but slightly more efficient than
Vector3d.length vector > tolerancesince the latter requires a square root under the hood. In many cases, however,
the speed difference will be negligible and using length is much more
readable!
Attempt to find the direction of a vector. In the case of a zero vector,
return Nothing.
Vector3d.direction (Vector3d ( 3, 0, 4 ))
--> Just (Direction3d ( 0.6, 0, 0.8 ))
Vector3d.direction (Vector3d ( 0, 0, 0 ))
--> NothingAttempt to find the length and direction of a vector. In the case of a zero
vector, returns Nothing.
vector =
Vector3d ( 3, 0, 4 )
Vector3d.lengthAndDirection vector
--> Just ( 5, Direction3d ( 0.6, 0, 0.8 ) )
Vector3d.lengthAndDirection Vector3d.zero
--> NothingAttempt 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, Nothing will be returned.
Vector3d.orthonormalize
( Vector3d ( 4, 3, 0 )
, Vector3d ( 0, 2, 0 )
, Vector3d ( 1, 2, 3 )
)
--> Just
--> ( Direction3d ( 0.8, 0.6, 0 )
--> , Direction3d ( -0.6, 0.8, 0 )
--> , Direction3d ( 0, 0, 1 )
--> )
Vector3d.orthonormalize
( Vector3d ( 2, 0, 0 )
, Vector3d ( 3, 1, 0 )
, Vector3d ( 4, 2, 0 )
)
--> NothingSee also Direction3d.orthogonalize.
Find the sum of two vectors.
firstVector =
Vector3d ( 1, 2, 3 )
secondVector =
Vector3d ( 4, 5, 6 )
Vector3d.sum firstVector secondVector
--> Vector3d ( 5, 7, 9 )Find the difference between two vectors (the first vector minus the second).
firstVector =
Vector3d ( 5, 6, 7 )
secondVector =
Vector3d ( 1, 1, 1 )
Vector3d.difference firstVector secondVector
--> Vector3d ( 4, 5, 6 )Find the dot product of two vectors.
firstVector =
Vector3d ( 1, 0, 2 )
secondVector =
Vector3d ( 3, 4, 5 )
Vector3d.dotProduct firstVector secondVector
--> 13Find the cross product of two vectors.
firstVector =
Vector3d ( 2, 0, 0 )
secondVector =
Vector3d ( 0, 3, 0 )
Vector3d.crossProduct firstVector secondVector
--> Vector3d ( 0, 0, 6 )Note that for all transformations, only the orientation of the given axis or plane is relevant, since vectors are position-independent. Think of transforming a vector as placing its tail on the relevant axis or plane and then transforming its tip.
Reverse the direction of a vector, negating its components.
Vector3d.flip (Vector3d ( 1, -3, 2 ))
--> Vector3d ( -1, 3, -2 )Scale the length of a vector by a given scale.
Vector3d.scaleBy 3 (Vector3d ( 1, 2, 3 ))
--> Vector3d ( 3, 6, 9 )Rotate a vector around a given axis by a given angle (in radians).
vector =
Vector3d ( 2, 0, 1 )
Vector3d.rotateAround Axis3d.x (degrees 90) vector
--> Vector3d ( 2, -1, 0 )
Vector3d.rotateAround Axis3d.z (degrees 45) vector
--> Vector3d ( 1.4142, 1.4142, 1 )Mirror a vector across a plane.
vector =
Vector3d ( 1, 2, 3 )
Vector3d.mirrorAcross Plane3d.xy vector
--> Vector3d ( 1, 2, -3 )
Vector3d.mirrorAcross Plane3d.yz vector
--> Vector3d ( -1, 2, 3 )Find the projection of a vector in a particular direction. Conceptually, this means splitting the original vector into a portion parallel to the given direction and a portion perpendicular to it, then returning the parallel portion.
vector =
Vector3d ( 1, 2, 3 )
Vector3d.projectionIn Direction3d.x vector
--> Vector3d ( 1, 0, 0 )
Vector3d.projectionIn Direction3d.z vector
--> Vector3d ( 0, 0, 3 )Project a vector onto a plane. Conceptually, this means splitting the original vector into a portion parallel to the plane (perpendicular to the plane's normal direction) and a portion perpendicular to it (parallel to its normal direction), then returning the parallel (in-plane) portion.
vector =
Vector3d ( 2, 1, 3 )
Vector3d.projectOnto Plane3d.xy vector
--> Vector3d ( 2, 1, 0 )
Vector3d.projectOnto Plane3d.xz vector
--> Vector3d ( 2, 0, 3 )Functions for transforming vectors between local and global coordinates in different coordinate frames. Like other transformations, coordinate transformations of vectors 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.rotateAround Axis3d.z (degrees 30) Frame3d.xyzTake a vector defined in global coordinates, and return it expressed in local coordinates relative to a given reference frame.
vector =
Vector3d ( 2, 0, 3 )
Vector3d.relativeTo rotatedFrame vector
--> Vector3d ( 1.732, -1, 3 )Take a vector defined in local coordinates relative to a given reference frame, and return that vector expressed in global coordinates.
vector =
Vector3d ( 2, 0, 3 )
Vector3d.placeIn rotatedFrame vector
--> Vector3d ( 1.732, 1, 3 )Functions for converting vectors between global 3D coordinates and 2D coordinates within a particular sketch plane.
Project a vector into a given sketch plane. Conceptually, this projects the vector onto the plane and then expresses the projected vector in 2D sketch coordinates.
vector =
Vector3d ( 2, 1, 3 )
Vector3d.projectInto SketchPlane3d.xy vector
--> Vector2d ( 2, 1 )
Vector3d.projectInto SketchPlane3d.yz vector
--> Vector2d ( 1, 3 )
Vector3d.projectInto SketchPlane3d.zx vector
--> Vector2d ( 3, 2 )
The zero vector.