ianmackenzie / elm-geometry-prerelease / Arc3d

An Arc3d is a section of a circle in 3D, defined by its central axis, start point and swept angle (the counterclockwise angle around the axis from the start point to the arc's end point). This module includes functionality for


type alias Arc3d =
Geometry.Types.Arc3d

Constructors

on : SketchPlane3d -> Arc2d -> Arc3d

Construct a 3D arc lying on a sketch plane by providing a 2D arc specified in XY coordinates within the sketch plane.

arc =
    Arc3d.on SketchPlane3d.xz
        (Point2d.fromCoordinates ( 3, 1 )
            |> Arc2d.sweptAround
                (Point2d.fromCoordinates ( 1, 1 )
                (degrees 90)
        )

Arc3d.centerPoint arc
--> Point3d.fromCoordinates ( 1, 0, 1 )

Arc3d.radius arc
--> 2

Arc3d.startPoint arc
--> Point3d.fromCoordinates ( 3, 0, 1 )

Arc3d.endPoint arc
--> Point3d.fromCoordinates ( 1, 0, 3 )

sweptAround : Axis3d -> Basics.Float -> Point3d -> Arc3d

Construct an arc by sweeping the given point around the given axis by the given angle:

exampleArc =
    Point3d.fromCoordinates ( 1, 1, 0 )
        |> Arc3d.sweptAround Axis3d.z (degrees 90)

Arc3d.centerPoint exampleArc
--> Point3d.origin

Arc3d.endPoint exampleArc
--> Point3d.fromCoordinates ( -1, 1, 0 )

Positive swept angles result in a counterclockwise (right-handed) rotation around the given axis and vice versa for negative swept angles. The center point of the returned arc will lie on the given axis.

throughPoints : Point3d -> Point3d -> Point3d -> Maybe Arc3d

Attempt to construct an arc that starts at the first given point, passes through the second given point and ends at the third given point. If the three points are collinear, returns Nothing.

p1 =
    Point3d.fromCoordinates ( 0, 0, 1 )

p2 =
    Point3d.origin

p3 =
    Point3d.fromCoordinates ( 0, 1, 0 )

Arc3d.throughPoints p1 p2 p3
--> Just
-->     (Arc3d.on SketchPlane3d.yz
-->         Point2d.fromCoordinates ( 0, 1 )
-->             |> Arc2d.sweptAround
-->                 (Point2d.fromCoordinates
-->                     ( 0.5, 0.5 )
-->                 )
-->                 (degrees 180)
-->     )

Properties

axialDirection : Arc3d -> Direction3d

Get the axial direction of an arc.

Arc3d.axialDirection exampleArc
--> Direction3d.z

axis : Arc3d -> Axis3d

Get the central axis of an arc. The origin point of the axis will be equal to the center point of the arc.

Arc3d.axis exampleArc
--> Axis3d.z

centerPoint : Arc3d -> Point3d

Get the center point of an arc.

Arc3d.centerPoint exampleArc
--> Point3d.origin

radius : Arc3d -> Basics.Float

Get the radius of an arc.

Arc3d.radius exampleArc
--> 1.4142

startPoint : Arc3d -> Point3d

Get the start point of an arc.

Arc3d.startPoint exampleArc
--> Point3d.fromCoordinates ( 1, 1, 0 )

endPoint : Arc3d -> Point3d

Get the end point of an arc.

Arc3d.endPoint exampleArc
--> Point3d.fromCoordinates ( -1, 1, 0 )

sweptAngle : Arc3d -> Basics.Float

Get the swept angle of an arc in radians.

Arc3d.sweptAngle exampleArc
--> 1.5708

A positive swept angle means that the arc is formed by rotating the given start point counterclockwise around the central axis, and vice versa for a negative angle.

Evaluation

pointOn : Arc3d -> Curve.ParameterValue.ParameterValue -> Point3d

Get the point along an arc at a given parameter value:

Arc3d.pointOn exampleArc ParameterValue.half
--> Point3d.fromCoordinates ( 0, 1.4142, 0 )

pointsAt : List Curve.ParameterValue.ParameterValue -> Arc3d -> List Point3d

Get points along an arc at a given set of parameter values.

exampleArc |> Arc3d.pointsAt (ParameterValue.steps 2)
--> [ Point3d ( 1, 1, 0 )
--> , Point3d ( 0, 1.4142, 0 )
--> , Point3d ( -1, 1, 0 )
--> ]


type Nondegenerate

If a curve has zero length (consists of just a single point), then we say that it is 'degenerate'. Some operations such as computing tangent directions are not defined on degenerate curves.

A Nondegenerate value represents an arc that is definitely not degenerate. It is used as input to functions such as Arc3d.tangentDirection and can be constructed using Arc3d.nondegenerate.

nondegenerate : Arc3d -> Result Point3d Nondegenerate

Attempt to construct a nondegenerate arc from a general Arc3d. If the arc is in fact degenerate (consists of a single point), returns an Err with that point.

Arc3d.nondegenerate exampleArc
--> Ok nondegenerateExampleArc

fromNondegenerate : Nondegenerate -> Arc3d

Convert a nondegenerate arc back to a general Arc3d.

Arc3d.fromNondegenerate nondegenerateExampleArc
--> exampleArc

tangentDirection : Nondegenerate -> Curve.ParameterValue.ParameterValue -> Direction3d

Get the tangent direction to a nondegenerate arc at a given parameter value:

Arc3d.tangentDirection nondegenerateExampleArc
    ParameterValue.zero
--> Direction3d.fromAzimuthAndElevation
-->     (degrees 135)
-->     (degrees 0)

Arc3d.tangentDirection nondegenerateExampleArc
    ParameterValue.half
--> Direction3d.negativeX

Arc3d.tangentDirection nondegenerateExampleArc
    ParameterValue.zero
--> Direction3d.fromAzimuthAndElevation
-->     (degrees 225)
-->     (degrees 0)

tangentDirectionsAt : List Curve.ParameterValue.ParameterValue -> Nondegenerate -> List Direction3d

Get tangent directions to a nondegenerate arc at a given set of parameter values:

nondegenerateExampleArc
    |> Arc3d.tangentDirectionsAt
        (ParameterValue.steps 2)
--> [ Direction3d.fromAzimuthAndElevation
-->     (degrees 135)
-->     (degrees 0)
--> , Direction3d.negativeX
--> , Direction3d.fromAzimuthAndElevation
-->     (degrees 225)
-->     (degrees 0)
--> ]

sample : Nondegenerate -> Curve.ParameterValue.ParameterValue -> ( Point3d, Direction3d )

Get both the point and tangent direction of a nondegenerate arc at a given parameter value:

Arc3d.sample nondegenerateExampleArc
    ParameterValue.zero
--> ( Point3d.fromCoordinates ( 1, 1, 0 )
--> , Direction3d.fromAzimuthAndElevation
-->     (degrees 135)
-->     (degrees 0)
--> )

Arc3d.sample nondegenerateExampleArc
    ParameterValue.half
--> ( Point3d.fromCoordinates ( 0, 1.4142, 0 )
--> , Direction3d.negativeX
--> )

Arc3d.sample nondegenerateExampleArc
    ParameterValue.one
--> ( Point3d.fromCoordinates ( -1, 1, 0 )
--> , Direction3d.fromAzimuthAndElevation
-->     (degrees 225)
-->     (degrees 0)
--> )

samplesAt : List Curve.ParameterValue.ParameterValue -> Nondegenerate -> List ( Point3d, Direction3d )

Get points and tangent directions of a nondegenerate arc at a given set of parameter values:

nondegenerateExampleArc
    |> Arc3d.samplesAt (ParameterValue.steps 2)
--> [ ( Point3d.fromCoordinates ( 1, 1, 0 )
-->   , Direction3d.fromAzimuthAndElevation
-->         (degrees 135)
-->         (degrees 0)
-->   )
--> , ( Point3d.fromCoordinates ( 0, 1.4142, 0 )
-->   , Direction3d.negativeX
-->   )
--> , ( Point3d.fromCoordinates ( -1, 1, 0 )
-->   , Direction3d.fromAzimuthAndElevation
-->         (degrees 225)
-->         (degrees 0)
-->   )
--> ]

If the arc is degenerate (start point and end point are equal), returns an empty list.

Linear approximation

toPolyline : { maxError : Basics.Float } -> Arc3d -> Polyline3d

Approximate an arc as a polyline, within a given tolerance:

exampleArc |> Arc3d.toPolyline { maxError = 0.1 }
--> Polyline3d.fromVertices
-->     [ Point3d.fromCoordinates ( 1, 1, 0 )
-->     , Point3d.fromCoordinates ( 0.366, 1.366, 0 )
-->     , Point3d.fromCoordinates ( -0.366, 1.366, 0 )
-->     , Point3d.fromCoordinates ( -1, 1, 0 )
-->     ]

In this example, every point on the returned polyline will be within 0.1 units of the original arc.

Transformations

reverse : Arc3d -> Arc3d

Reverse the direction of an arc, so that the start point becomes the end point and vice versa. The resulting arc will have the same axis as the original but a swept angle with the opposite sign.

Arc3d.reverse exampleArc
--> Arc3d.sweptAround Axis3d.z
-->     (degrees -90)
-->     (Point3d.fromCoordinates ( -1, 1, 0 ))

scaleAbout : Point3d -> Basics.Float -> Arc3d -> Arc3d

Scale an arc about the given center point by the given scale.

point =
    Point3d.fromCoordinates ( 0, -1, 0 )

Arc3d.scaleAbout point 2 exampleArc
--> Arc3d.sweptAround
-->     (Axis3d.withDirection Direction3d.z
-->         (Point3d.fromCoordinates ( 0, 1, 0 ))
-->     )
-->     (degrees 90)
-->     (Point3d.fromCoordinates ( 2, 3, 0 ))

rotateAround : Axis3d -> Basics.Float -> Arc3d -> Arc3d

Rotate an arc around a given axis by a given angle (in radians).

Arc3d.rotateAround Axis3d.x (degrees 90) exampleArc
--> Arc3d.sweptAround (Axis3d.reverse Axis3d.y)
-->     (degrees 90)
-->     (Point3d.fromCoordinates ( 1, 0, 1 ))

translateBy : Vector3d -> Arc3d -> Arc3d

Translate an arc by a given displacement.

displacement =
    Vector3d.fromComponents ( 2, 1, 3 )

Arc3d.translateBy displacement exampleArc
--> Arc3d.sweptAround
-->     (Axis3d.withDirection Direction3d.z
-->         (Point3d ( 2, 1, 3 ))
-->     )
-->     (degrees 90)
-->     (Point3d.fromCoordinates ( 3, 2, 3 ))

translateIn : Direction3d -> Basics.Float -> Arc3d -> Arc3d

Translate an arc in a given direction by a given distance;

Arc3d.translateIn direction distance

is equivalent to

Arc3d.translateBy
    (Vector3d.withLength distance direction)

mirrorAcross : Plane3d -> Arc3d -> Arc3d

Mirror an arc across a given plane.

Arc3d.mirrorAcross Plane3d.xy exampleArc
--> Arc3d.sweptAround (Axis3d.reverse Axis3d.z)
-->     (degrees -90)
-->     (Point3d.fromCoordinates ( 1, 1, 0 ))

Note that this flips the sign of the arc's swept angle.

projectInto : SketchPlane3d -> Arc3d -> Geometry.Types.EllipticalArc2d

Project an arc into a sketch plane.

axis : Axis3d
axis =
    Axis3d.through
        (Point3d.fromCoordinates ( 1, 2, 3 ))
        (Direction3d.fromAzimuthAndElevation
            (degrees 0)
            (degrees 45)
        )

arc : Arc3d
arc =
    Arc3d.sweptAround axis
        (degrees 45)
        (Point3d.fromCoordinates ( 1, 4, 3 ))

Arc3d.projectInto SketchPlane3d.xy arc
--> EllipticalArc2d.with
-->     { centerPoint =
-->         Point2d.fromCoordinates ( 1, 2 )
-->     , xDirection = Direction2d.y
-->     , xRadius = 2
-->     , yRadius = 1.4142
-->     , startAngle = degrees 0
-->     , sweptAngle = degrees 45
-->     }

Coordinate conversions

relativeTo : Frame3d -> Arc3d -> Arc3d

Take an arc defined in global coordinates, and return it expressed in local coordinates relative to a given reference frame.

localFrame =
    Frame3d.atPoint
        (Point3d.fromCoordinates ( 1, 2, 3 ))

Arc3d.relativeTo localFrame exampleArc
--> Arc3d.sweptAround
-->     (Axis3d.withDirection Direction3d.z
-->         (Point3d ( -1, -2, -3 ))
-->     )
-->     (degrees 90)
-->     (Point3d.fromCoordinates ( 0, -1, -3 ))

placeIn : Frame3d -> Arc3d -> Arc3d

Take an arc considered to be defined in local coordinates relative to a given reference frame, and return that arc expressed in global coordinates.

localFrame =
    Frame3d.atPoint
        (Point3d.fromCoordinates ( 1, 2, 3 ))

Arc3d.placeIn localFrame exampleArc
--> Arc3d.sweptAround
-->     (Axis3d.withDirection Direction3d.z
-->         (Point3d.fromCoordinates ( 1, 2, 3 ))
-->     )
-->     (degrees 90)
-->     (Point3d.fromCoordinates ( 2, 3, 3 ))

Differentiation

You are unlikely to need to use these functions directly, but they are useful if you are writing low-level geometric algorithms.

firstDerivative : Arc3d -> Curve.ParameterValue.ParameterValue -> Vector3d

Get the first derivative of an arc at a given parameter value.

Arc3d.firstDerivative exampleArc ParameterValue.zero
--> Vector3d.fromComponents ( -1.5708, 1.5708, 0 )

Arc3d.firstDerivative exampleArc ParameterValue.one
--> Vector3d.fromComponents ( -1.5708, -1.5708, 0 )

firstDerivativesAt : List Curve.ParameterValue.ParameterValue -> Arc3d -> List Vector3d

Evaluate the first derivative of an arc at a range of parameter values.

exampleArc
    |> Arc3d.firstDerivativesAt
        (ParameterValue.steps 2)
--> [ Vector3d ( -1.5708, 1.5708, 0 )
--> , Vector3d ( -2.2214, 0, 0 )
--> , Vector3d ( -1.5708, -1.5708, 0 )
--> ]