A Point3d represents a position in 3D space and is defined by its X, Y and Z
coordinates. This module contains a variety of point-related functionality, such
as
The simplest way to construct a Point3d value is by passing a tuple of X, Y
and Z coordinates to the Point3d constructor, for example
point =
Point3d ( 2, 1, 3 )Construct a point halfway between two other points.
p1 =
Point3d ( 1, 1, 1 )
p2 =
Point3d ( 3, 7, 9 )
Point3d.midpoint p1 p2
--> Point3d ( 2, 4, 5 )Construct a point by interpolating from the first given point to the second, based on a parameter that ranges from zero to one.
startPoint =
Point3d ( 1, 2, 4 )
endPoint =
Point3d ( 1, 2, 8 )
Point3d.interpolateFrom startPoint endPoint 0.25
--> Point3d ( 1, 2, 5 )Partial application may be useful:
interpolatedPoint : Float -> Point3d
interpolatedPoint =
Point3d.interpolateFrom startPoint endPoint
List.map interpolatedPoint [ 0, 0.5, 1 ]
--> [ Point3d ( 1, 2, 4 )
--> , Point3d ( 1, 2, 6 )
--> , Point3d ( 1, 2, 8 )
--> ]You can pass values less than zero or greater than one to extrapolate:
interpolatedPoint -0.5
--> Point3d ( 1, 2, 2 )
interpolatedPoint 1.25
--> Point3d ( 1, 2, 9 )DEPRECATED: Alias for interpolateFrom, kept for compatibility. Use
interpolateFrom instead.
Construct a point along an axis at a particular distance from the axis' origin point.
Point3d.along Axis3d.z 2
--> Point3d ( 0, 0, 2 )Positive and negative distances are interpreted relative to the direction of the axis:
horizontalAxis =
Axis3d
{ originPoint = Point3d ( 1, 1, 1 )
, direction = Direction3d ( -1, 0, 0 )
}
Point3d.along horizontalAxis 3
--> Point3d ( -2, 1, 1 )
Point3d.along horizontalAxis -3
--> Point3d ( 4, 1, 1 )Construct a point on a sketch plane with the given local coordinates.
Point3d.on SketchPlane3d.xz ( 2, 3 )
--> Point3d ( 2, 0, 3 )This is shorthand for using Point2d.placeOnto;
Point3d.on sketchPlane coordinatesis equivalent to
Point2d coordinates |> Point2d.placeOnto sketchPlaneConstruct a point given its local coordinates within a particular frame.
frame =
Frame3d.at (Point3d ( 1, 1, 1 ))
Point3d.in_ frame ( 1, 2, 3 )
--> Point3d ( 2, 3, 4 )This is shorthand for using Point3d.placeIn;
Point3d.in_ frame coordinatesis equivalent to
Point3d coordinates |> Point3d.placeIn frameGet the coordinates of a point as a tuple.
( x, y, z ) =
Point3d.coordinates pointGet the X coordinate of a point.
Point3d.xCoordinate (Point3d ( 2, 1, 3 ))
--> 2Get the Y coordinate of a point.
Point3d.yCoordinate (Point3d ( 2, 1, 3 ))
--> 1Get the Z coordinate of a point.
Point3d.zCoordinate (Point3d ( 2, 1, 3 ))
--> 3Compare two points within a tolerance. Returns true if the distance between the two given points is less than the given tolerance.
firstPoint =
Point3d ( 2, 1, 3 )
secondPoint =
Point3d ( 2.0002, 0.9999, 3.0001 )
Point3d.equalWithin 1e-3 firstPoint secondPoint
--> True
Point3d.equalWithin 1e-6 firstPoint secondPoint
--> FalseFind the vector from one point to another.
startPoint =
Point3d ( 1, 1, 1 )
endPoint =
Point3d ( 4, 5, 6 )
Point3d.vectorFrom startPoint endPoint
--> Vector3d ( 3, 4, 5 )Attempt to find the direction from the first point to the second. If the two
points are coincident, returns Nothing.
point =
Point3d ( 1, 0, 1 )
Point3d.directionFrom Point3d.origin point
--> Just (Direction3d ( 0.7071, 0, 0.7071 ))
Point3d.directionFrom point Point3d.origin
--> Just (Direction3d ( -0.7071, 0, -0.7071 ))
Point3d.directionFrom point point
--> NothingFind the distance between two points.
p1 =
Point3d ( 1, 1, 2 )
p2 =
Point3d ( 2, 3, 4 )
Point3d.distanceFrom p1 p2
--> 3Partial application can be useful:
points =
[ Point3d ( 3, 4, 5 )
, Point3d ( 10, 10, 10 )
, Point3d ( -1, 2, -3 )
]
distanceFromOrigin : Point3d -> Float
distanceFromOrigin =
Point3d.distanceFrom Point3d.origin
List.sortBy distanceFromOrigin points
--> [ Point3d ( -1, 2, -3 )
--> , Point3d ( 3, 4, 5 )
--> , Point3d ( 10, 10, 10 )
--> ]Find the square of the distance from one point to another.
squaredDistanceFrom is slightly faster than distanceFrom, so for example
Point3d.squaredDistanceFrom p1 p2 > tolerance * toleranceis equivalent to but slightly more efficient than
Point3d.distanceFrom p1 p2 > tolerancesince the latter requires a square root under the hood. In many cases, however,
the speed difference will be negligible and using distanceFrom is much more
readable!
Determine how far along an axis a particular point lies. Conceptually, the point is projected perpendicularly onto the axis, and then the distance of this projected point from the axis' origin point is measured. The result will be positive if the projected point is ahead the axis' origin point and negative if it is behind, with 'ahead' and 'behind' defined by the direction of the axis.
axis =
Axis3d
{ originPoint = Point3d ( 1, 0, 0 )
, direction = Direction3d.x
}
point =
Point3d ( 3, 3, 3 )
Point3d.distanceAlong axis point
--> 2
Point3d.distanceAlong axis Point3d.origin
--> -1Find the perpendicular (nearest) distance of a point from an axis.
point =
Point3d ( -3, 4, 0 )
Point3d.radialDistanceFrom Axis3d.x point
--> 4
Point3d.radialDistanceFrom Axis3d.y point
--> 3
Point3d.radialDistanceFrom Axis3d.z point
--> 5Note that unlike in 2D, the result is always positive (unsigned) since there is no such thing as the left or right side of an axis in 3D.
Find the square of the perpendicular distance of a point from an axis. As
with distanceFrom/squaredDistanceFrom this is slightly more efficient than
radialDistanceFrom since it avoids a square root.
Find the perpendicular distance of a point from a plane. The result will be positive if the point is 'above' the plane and negative if it is 'below', with 'up' defined by the normal direction of the plane.
plane =
Plane3d
{ originPoint = Point3d ( 1, 2, 3 )
, normalDirection = Direction3d.y
}
point =
Point3d ( 3, 3, 3 )
Point3d.signedDistanceFrom plane point
--> 1
Point3d.signedDistanceFrom plane Point3d.origin
--> -2This means that flipping a plane (reversing its normal direction) will also flip the sign of the result of this function:
flippedPlane =
Plane3d.flip plane
Point3d.signedDistanceFrom flippedPlane point
--> -1Perform a uniform scaling about the given center point. The center point is given first and the point to transform is given last. Points will contract or expand about the center point by the given scale. Scaling by a factor of 1 is a no-op, and scaling by a factor of 0 collapses all points to the center point.
centerPoint =
Point3d ( 1, 1, 1 )
point =
Point3d ( 1, 2, 3 )
Point3d.scaleAbout centerPoint 3 point
--> Point3d ( 1, 4, 7 )
Point3d.scaleAbout centerPoint 0.5 point
--> Point3d ( 1, 1.5, 2 )Avoid scaling by a negative scaling factor - while this may sometimes do what you want it is confusing and error prone. Try a combination of mirror and/or rotation operations instead.
Rotate a point around an axis by a given angle (in radians).
axis =
Axis3d.x
angle =
degrees 45
point =
Point3d ( 3, 1, 0 )
Point3d.rotateAround axis angle point
--> Point3d ( 3, 0.7071, 0.7071 )Rotation direction is given by the right-hand rule, counterclockwise around the direction of the axis.
Translate a point by a given displacement.
point =
Point3d ( 3, 4, 5 )
displacement =
Vector3d ( 1, 2, 3 )
Point3d.translateBy displacement point
--> Point3d ( 4, 6, 8 )Mirror a point across a plane. The result will be the same distance from the plane but on the opposite side.
point =
Point3d ( 1, 2, 3 )
-- Plane3d.xy is the plane Z=0
Point3d.mirrorAcross Plane3d.xy point
--> Point3d ( 1, 2, -3 )
-- Plane3d.yz is the plane X=0
Point3d.mirrorAcross Plane3d.yz point
--> Point3d ( -1, 2, 3 )The plane does not have to pass through the origin:
-- offsetPlane is the plane Z=1
offsetPlane =
Plane3d.offsetBy 1 Plane3d.xy
-- The origin point is 1 unit below the offset
-- plane, so its mirrored copy is one unit above
Point3d.mirrorAcross offsetPlane Point3d.origin
--> Point3d ( 0, 0, 2 )Project a point perpendicularly onto a plane.
point =
Point3d ( 1, 2, 3 )
Point3d.projectOnto Plane3d.xy point
--> Point3d ( 1, 2, 0 )
Point3d.projectOnto Plane3d.yz point
--> Point3d ( 0, 2, 3 )The plane does not have to pass through the origin:
offsetPlane =
Plane3d.offsetBy 1 Plane3d.xy
Point3d.projectOnto offsetPlane point
--> Point3d ( 1, 2, 1 )Project a point perpendicularly (radially) onto an axis.
point =
Point3d ( 1, 2, 3 )
Point3d.projectRadiallyOnto Axis3d.x
--> Point3d ( 1, 0, 0 )
verticalAxis =
Axis3d
{ originPoint = Point3d ( 0, 1, 2 )
, direction = Direction3d.z
}
Point3d.projectRadiallyOnto verticalAxis
--> Point3d ( 0, 1, 3 )Functions for transforming points between local and global coordinates in different coordinate frames.
Take a point defined in global coordinates, and return it expressed in local coordinates relative to a given reference frame.
localFrame =
Frame3d.at (Point3d ( 1, 2, 3 ))
Point3d.relativeTo localFrame (Point3d ( 4, 5, 6 ))
--> Point3d ( 3, 3, 3 )
Point3d.relativeTo localFrame (Point3d ( 1, 1, 1 ))
--> Point3d ( 0, -1, -2 )Take a point defined in local coordinates relative to a given reference frame, and return that point expressed in global coordinates.
localFrame =
Frame3d.at (Point3d ( 1, 2, 3 ))
Point3d.placeIn localFrame (Point3d ( 3, 3, 3 ))
--> Point3d ( 4, 5, 6 )
Point3d.placeIn localFrame (Point3d ( 0, -1, -2 ))
--> Point3d ( 1, 1, 1 )Project a point into a given sketch plane. Conceptually, this projects the point onto the plane and then expresses the projected point in 2D sketch coordinates.
point =
Point3d ( 2, 1, 3 )
Point3d.projectInto SketchPlane3d.xy point
--> Point2d ( 2, 1 )
Point3d.projectInto SketchPlane3d.yz point
--> Point2d ( 1, 3 )
Point3d.projectInto SketchPlane3d.zx point
--> Point2d ( 3, 2 )Construct a bounding box containing both of the given points.
point1 =
Point3d ( 2, 1, 3 )
point2 =
Point3d ( -1, 5, -2 )
Point3d.hull point1 point2
--> BoundingBox3d
--> { minX = -1
--> , maxX = 2
--> , minY = 1
--> , maxY = 5
--> , minZ = -2
--> , maxZ = 3
--> }
The point (0, 0, 0).