A Vector2d represents a quantity such as a displacement or velocity in 2D, and
is defined by its X and Y 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 Point2d
and Direction2d than Vector2d, and much code can avoid working directly with
Vector2d values at all!
The simplest way to create a Vector2d is by passing a tuple of X and Y
components to the Vector2d constructor, for example
vector =
Vector2d ( 2, 3 )There are no specific functions to create vectors from polar components, but you
can use Elm's built-in fromPolar
function:
vector =
Vector2d (fromPolar ( radius, angle ))Although there are no predefined constants for
Vector2d ( 1, 0 ) and
Vector2d ( 0, 1 ), in most cases you will
actually want their Direction2d versions Direction2d.x
and Direction2d.y.
Construct a vector perpendicular to the given vector, by rotating the given vector 90 degrees counterclockwise. The constructed vector will have the same length as the given vector.
Vector2d.perpendicularTo (Vector2d ( 1, 0 ))
--> Vector2d ( 0, 1 )
Vector2d.perpendicularTo (Vector2d ( 0, 2 ))
--> Vector2d ( -2, 0 )
Vector2d.perpendicularTo (Vector2d ( 3, 1 ))
--> Vector2d ( -1, 3 )
Vector2d.perpendicularTo Vector2d.zero
--> Vector2d.zeroExtract the components of a vector.
Vector2d.components (Vector2d ( 2, 3 ))
--> ( 2, 3 )This combined with Elm's built-in tuple destructuring provides a convenient way to extract both the X and Y components of a vector in one line of code:
( x, y ) =
Vector2d.components vectorTo get the polar components of a vector, you can use Elm's built-in toPolar
function:
( radius, angle ) =
toPolar (Vector2d.components vector)Get the X component of a vector.
Vector2d.xComponent (Vector2d ( 2, 3 ))
--> 2Get the Y component of a vector.
Vector2d.yComponent (Vector2d ( 2, 3 ))
--> 3Find the component of a vector in an arbitrary direction, for example
forwardSpeed =
Vector2d.componentIn forwardDirection velocityThis is more general and flexible than using xComponent or yComponent, both
of which can be expressed in terms of componentIn; for example,
Vector2d.xComponent vectoris equivalent to
Vector2d.componentIn Direction2d.x vectorCompare two vectors within a tolerance. Returns true if the difference between the two given vectors has magnitude less than the given tolerance.
firstVector =
Vector2d ( 1, 2 )
secondVector =
Vector2d ( 0.9999, 2.0002 )
Vector2d.equalWithin 1e-3 firstVector secondVector
--> True
Vector2d.equalWithin 1e-6 firstVector secondVector
--> FalseGet the length (magnitude) of a vector.
Vector2d.length (Vector2d ( 3, 4 ))
--> 5Get the squared length of a vector. squaredLength is slightly faster than
length, so for example
Vector2d.squaredLength vector > tolerance * toleranceis equivalent to but slightly more efficient than
Vector2d.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.
Vector2d.direction (Vector2d ( 3, 4 ))
--> Just (Direction2d ( 0.6, 0.8 ))
Vector2d.direction (Vector2d ( 0, 0 ))
--> NothingAttempt to find the length and direction of a vector. In the case of a zero
vector, returns Nothing.
vector =
Vector2d ( 3, 4 )
Vector2d.lengthAndDirection vector
--> Just ( 5, Direction2d ( 0.6, 0.8 ) )
Vector2d.lengthAndDirection Vector2d.zero
--> NothingFind the sum of two vectors.
firstVector =
Vector2d ( 1, 2 )
secondVector =
Vector2d ( 3, 4 )
Vector2d.sum firstVector secondVector
--> Vector2d ( 4, 6 )Find the difference between two vectors (the first vector minus the second).
firstVector =
Vector2d ( 5, 6 )
secondVector =
Vector2d ( 1, 3 )
Vector2d.difference firstVector secondVector
--> Vector2d ( 4, 3 )Find the dot product of two vectors.
firstVector =
Vector2d ( 1, 2 )
secondVector =
Vector2d ( 3, 4 )
Vector2d.dotProduct firstVector secondVector
--> 11Find the scalar 'cross product' of two vectors in 2D. This is defined as
crossProduct firstVector secondVector =
let
( x1, y1 ) =
components firstVector
( x2, y2 ) =
components secondVector
in
x1 * y2 - y1 * x2and is useful in many of the same ways as the 3D cross product:
Some examples:
firstVector =
Vector2d ( 2, 0 )
secondVector =
Vector2d ( 0, 3 )
Vector2d.crossProduct firstVector secondVector
--> 6
Vector2d.crossProduct secondVector firstVector
--> -6
Vector2d.crossProduct firstVector firstVector
--> 0Note that for mirrorAcross and projectOnto, only the direction of the axis
affects the result, since vectors are position-independent. Think of
mirroring/projecting a vector across/onto an axis as moving the vector so its
tail is on the axis, then mirroring/projecting its tip across/onto the axis.
Reverse the direction of a vector, negating its components.
Vector2d.flip (Vector2d ( -1, 2 ))
--> Vector2d ( 1, -2 )Scale the length of a vector by a given scale.
Vector2d.scaleBy 3 (Vector2d ( 1, 2 ))
--> Vector2d ( 3, 6 )Rotate a vector counterclockwise by a given angle (in radians).
Vector2d.rotateBy (degrees 45) (Vector2d ( 1, 1 ))
--> Vector2d ( 0, 1.4142 )
Vector2d.rotateBy pi (Vector2d ( 1, 0 ))
--> Vector2d ( -1, 0 )Mirror a vector across a given axis.
vector =
Vector2d ( 2, 3 )
Vector2d.mirrorAcross Axis2d.y vector
--> Vector2d ( -2, 3 )
horizontalAxis =
Axis2d
{ originPoint = Point2d ( 100, 200 )
, direction = Direction2d.x
}
Vector2d.mirrorAcross horizontalAxis vector
--> Vector2d ( 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 =
Vector2d ( 2, 3 )
Vector2d.projectionIn Direction2d.x vector
--> Vector2d ( 2, 0 )
Vector2d.projectionIn Direction2d.y vector
--> Vector2d ( 0, 3 )Project a vector onto an axis.
Vector2d.projectOnto Axis2d.y (Vector2d ( 3, 4 ))
--> Vector2d ( 0, 4 )
Vector2d.projectOnto Axis2d.x (Vector2d ( -1, 2 ))
--> Vector2d ( -1, 0 )This is equivalent to finding the projection in the axis' direction.
Functions for transforming vectors between local and global coordinates in different coordinate frames. Like other transformations, coordinate conversions of vectors depend only on the orientations of the relevant frames, not the positions of their origin points.
For the examples, assume the following frame has been defined:
rotatedFrame =
Frame2d.rotateBy (degrees 30) Frame2d.xyTake a vector defined in global coordinates, and return it expressed in local coordinates relative to a given reference frame.
Vector2d.relativeTo rotatedFrame (Vector2d ( 2, 0 ))
--> Vector2d ( 1.732, -1 )Take a vector defined in local coordinates relative to a given reference frame, and return that vector expressed in global coordinates.
Vector2d.placeIn rotatedFrame (Vector2d ( 2, 0 ))
--> Vector2d ( 1.732, 1 )Take a vector defined in 2D coordinates within a particular sketch plane and return the corresponding vector in 3D.
vector =
Vector2d ( 2, 3 )
Vector2d.placeOnto SketchPlane3d.xy vector
--> Vector3d ( 2, 3, 0 )
Vector2d.placeOnto SketchPlane3d.yz vector
--> Vector3d ( 0, 2, 3 )
Vector2d.placeOnto SketchPlane3d.zx vector
--> Vector3d ( 3, 0, 2 )A slightly more complex example:
tiltedSketchPlane =
SketchPlane3d.xy
|> SketchPlane3d.rotateAround Axis3d.x (degrees 45)
Vector2d.placeOnto tiltedSketchPlane (Vector2d ( 1, 1 ))
--> Vector3d ( 1, 0.7071, 0.7071 )
The zero vector.