A Frame3d has an origin point and a set of X, Y and Z directions (which are
always perpendicular to each other). It can be thought of as:
relativeTo
and placeIn functions that convert values of that type from global
coordinates to local coordinates in a particular frame, and vice versa.Frame3d could be
used to define the position and orientation of a spaceship in a 3D game.
Movement of the ship would then be done by translating and rotating the
frame.Frames can by constructed by passing a record with originPoint, xDirection,
yDirection and zDirection fields to the Frame3d constructor, for example:
frame =
Frame3d
{ originPoint = Point3d ( 2, 1, 3 )
, xDirection = Direction3d ( 0.8, 0.6, 0 )
, yDirection = Direction3d ( -0.6, 0.8, 0 )
, zDirection = Direction3d ( 0, 0, 1)
}In this case you must be careful to ensure that the X, Y and Z directions are perpendicular. (You will likely also want to make sure that they form a right-handed coordinate system.)
Construct a frame aligned with the global XYZ frame but with the given origin point.
Frame3d.at (Point3d ( 2, 1, 3 ))
--> Frame3d
--> { originPoint = Point3d ( 2, 1, 3 )
--> , xDirection = Direction3d.x
--> , yDirection = Direction3d.y
--> , zDirection = Direction3d.z
--> }Get the origin point of a given frame.
Frame3d.originPoint Frame3d.xyz
--> Point3d.originGet the X direction of a given frame.
Frame3d.xDirection Frame3d.xyz
--> Direction3d.xGet the Y direction of a given frame.
Frame3d.yDirection Frame3d.xyz
--> Direction3d.yGet the Z direction of a given frame.
Frame3d.zDirection Frame3d.xyz
--> Direction3d.zGet the X axis of a given frame (the axis formed from the frame's origin point and X direction).
Frame3d.xAxis Frame3d.xyz
--> Axis3d.xGet the Y axis of a given frame (the axis formed from the frame's origin point and Y direction).
Frame3d.yAxis Frame3d.xyz
--> Axis3d.yGet the Z axis of a given frame (the axis formed from the frame's origin point and Z direction).
Frame3d.zAxis Frame3d.xyz
--> Axis3d.zThe following functions all return planes with the same origin point as the given plane, but with varying normal directions. In each case the normal direction of the resulting plane is given by the cross product of the two indicated basis directions (assuming a right-handed frame); for example,
Frame3d.xyPlane Frame3d.xyz
--> Plane3d
--> { originPoint = Point3d.origin
--> , normalDirection = Direction3d.z
--> }since the cross product of the X and Y basis directions of a frame is equal to its Z basis direction. And since reversing the order of arguments in a cross product reverses the sign of the result,
Frame3d.yxPlane Frame3d.xyz
--> Plane3d
--> { originPoint = Point3d.origin
--> , normalDirection = Direction3d.flip Direction3d.z
--> }Get a plane with normal direction equal to the frame's positive Z direction.
Get a plane with normal direction equal to the frame's negative Z direction.
Get a plane with normal direction equal to the frame's positive X direction.
Get a plane with normal direction equal to the frame's negative X direction.
Get a plane with normal direction equal to the frame's positive Y direction.
Get a plane with normal direction equal to the frame's negative Y direction.
These functions all form a SketchPlane3d from two axes of the given frame. The
X and Y axes of the sketch plane will correspond to the two indicated axes. For
example,
Frame3d.yzSketchPlane Frame3d.xyz
--> SketchPlane3d
--> { originPoint = Point3d.origin
--> , xDirection = Direction3d.y
--> , yDirection = Direction3d.z
--> }Note that this can be confusing - for example, a local X coordinate in the above sketch plane corresponds to a global Y coordinate, and a local Y coordinate corresponds to a global Z coordinate!
Form a sketch plane from the given frame's X and Y axes.
Form a sketch plane from the given frame's Y and X axes.
Form a sketch plane from the given frame's Y and Z axes.
Form a sketch plane from the given frame's Z and Y axes.
Form a sketch plane from the given frame's Z and X axes.
Form a sketch plane from the given frame's X and Z axes.
Reverse the X direction of a frame.
Frame3d.flipX Frame3d.xyz
--> Frame3d
--> { originPoint = Point3d.origin
--> , xDirection = Direction3d.flip Direction3d.x
--> , yDirection = Direction3d.y
--> , zDirection = Direction3d.z
--> }Reverse the Y direction of a frame.
Frame3d.flipY Frame3d.xyz
--> Frame3d
--> { originPoint = Point3d.origin
--> , xDirection = Direction3d.x
--> , yDirection = Direction3d.flip Direction3d.y
--> , zDirection = Direction3d.z
--> }Reverse the Z direction of a frame.
Frame3d.flipZ Frame3d.xyz
--> Frame3d
--> { originPoint = Point3d.origin
--> , xDirection = Direction3d.x
--> , yDirection = Direction3d.y
--> , zDirection = Direction3d.flip Direction3d.z
--> }Move a frame so that it has the given origin point but same orientation.
point =
Point3d ( 2, 1, 3 )
Frame3d.at point
--> Frame3d
--> { originPoint = Point3d ( 2, 1, 3 )
--> , xDirection = Direction3d.x
--> , yDirection = Direction3d.y
--> , zDirection = Direction3d.z
--> }Rotate a frame around an axis by a given angle (in radians). The frame's origin point and basis directions will all be rotated around the given axis.
frame =
Frame3d.at (Point3d ( 2, 1, 3 ))
Frame3d.rotateAround Frame3d.zAxis (degrees 90) frame
--> Frame3d
--> { originPoint = Point3d ( -1, 2, 3 )
--> , xDirection = Direction3d.y
--> , yDirection = Direction3d.flip Direction3d.x
--> , zDirection = Direction3d.z
--> }Rotate a frame around one of its own axes by a given angle (in radians).
The first argument is a function that returns the axis to rotate around, given
the current frame. The majority of the time this will be either Frame3d.xAxis,
Frame3d.yAxis or Frame3d.zAxis. Compare the following to the above example
for rotateAround:
frame =
Frame3d.at (Point3d ( 2, 1, 3 ))
Frame3d.rotateAroundOwn Frame3d.zAxis (degrees 90) frame
--> Frame3d
--> { originPoint = Point3d ( 2, 1, 3 )
--> , xDirection = Direction3d.y
--> , yDirection = Direction3d.flip Direction3d.x
--> , zDirection = Direction3d.z
--> }Since the rotation is done around the frame's own Z axis (which passes through the frame's origin point), the origin point remains the same after rotation.
In this example the frame's Z axis has the same orientation as the global Z axis so the frame's basis directions are rotated the same way, but in more complex examples involving rotated frames a rotation around (for example) the frame's own Z axis may be completely different from a rotation around the global Z axis.
Translate a frame by a given displacement.
frame =
Frame3d.at (Point3d ( 2, 1, 3 ))
displacement =
Vector3d ( 1, 1, 1 )
Frame3d.translateBy displacement frame
--> Frame3d.at (Point3d ( 3, 2, 4 ))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 will be either Frame3d.xAxis,
Frame3d.yAxis or Frame3d.zAxis.
This function is convenient when constructing frames via a series of transformations. For example,
Frame3d.at (Point3d ( 2, 0, 0 ))
|> Frame3d.rotateAroundOwn Frame3d.zAxis (degrees 45)
|> Frame3d.translateAlongOwn Frame3d.xAxis 2means "construct a frame at the point (2, 0, 0), rotate it around its own Z axis by 45 degrees, then translate it along its own (rotated) X axis by 2 units", resulting in
Frame3d
{ originPoint = Point3d ( 3.4142, 1.4142, 0 )
, xDirection = Direction3d ( 0.7071, 0.7071, 0 )
, yDirection = Direction3d ( -0.7071, 0.7071, 0)
, zDirection = Direction3d.z
}Mirror a frame across a plane.
frame =
Frame3d.at (Point3d ( 2, 1, 3 ))
Frame3d.mirrorAcross Plane3d.xy frame
--> Frame3d
--> { originPoint = Point3d ( 2, 1, -3 )
--> , xDirection = Direction3d.x
--> , yDirection = Direction3d.y
--> , zDirection = Direction3d.flip Direction3d.z
--> }Note that this will switch the handedness of the frame.
Take two frames defined in global coordinates, and return the second one expressed in local coordinates relative to the first.
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.
The global XYZ frame.