opensolid/geometry/2.1.0

NOTE: this package is not compatible with Elm 0.19.1

OpenSolid.EllipticalArc2d

EllipticalArc2d

An EllipticalArc2d is a section of an Ellipse2d with a start and end point. This module includes functionality for

  • Constructing an elliptical arc from its center or end points
  • Scaling, rotating, translating and mirroring elliptical arcs
  • Evaluating points and derivative vectors along elliptical arcs
  • Forming arc length parameterizations of elliptical arcs

The startAngle and sweptAngle values referred to below are not actually proper angles but instead refer to values of the ellipse parameter. However, in simple cases you don't need to worry about the difference - if startAngle and sweptAngle are both multiples of 90 degrees, then you can treat them as actual angles and everything will work out.

type alias EllipticalArc2d =
EllipticalArc2d

An elliptical arc in 2D.

Constructors

{ centerPoint : Point2d
, xDirection : Direction2d
, xRadius : Float
, yRadius : Float
, startAngle : Float
, sweptAngle : Float
}
-> EllipticalArc2d

Construct an elliptical arc from its center point, X direction, X and Y radii, start angle and swept angle. Any negative sign on xRadius or yRadius will be ignored (the absolute values will be used).

For example, to construct a simple 90 degree elliptical arc, you might use

exampleArc =
    EllipticalArc2d.with
        { centerPoint = Point2d.origin
        , xDirection = Direction2d.x
        , xRadius = 2
        , yRadius = 1
        , startAngle = 0
        , sweptAngle = degrees 90
        }

90 degree elliptical arc

To make an inclined 180 degree elliptical arc, you might use

EllipticalArc2d.with
    { centerPoint = Point2d.origin
    , xDirection = Direction2d.fromAngle (degrees 30)
    , xRadius = 2
    , yRadius = 1
    , startAngle = degrees -90
    , sweptAngle = degrees 180
    }

180 degree inclined elliptical arc

{ startPoint : Point2d
, endPoint : Point2d
, xDirection : Direction2d
, xRadius : Float
, yRadius : Float
, sweptAngle : SweptAngle
}
-> Maybe EllipticalArc2d

Attempt to construct an elliptical arc from its endpoints, X direction, and X and Y radii. For any given valid set of these inputs, there are four possible solutions, so you also need to specify which of the four solutions you want - whether the swept angle of the arc should be less than or greater than 180 degrees, and whether the swept angle should be positive (counterclockwise) or negative (clockwise).

The example below is interactive; try dragging either endpoint or the tip of the X direction (or the center point to move the whole arc), clicking on the X or Y radial lines and then scrolling to changet that radius, or clicking/tapping on the various dashed arcs to switch what kind of swept angle to use.

https://opensolid.github.io/geometry/2.1.0/doc/interactive/EllipticalArc2d/fromEndpoints.html

This function will return Nothing if no solution can found. Typically this means that the two endpoints are too far apart, but could also mean that one of the specified radii was negative or zero, or the two given points were coincident.

The behavior of this function is very close to the SVG spec, but when 'out of range' parameters are given this function will simply return Nothing instead of attempting to degrade gracefully (for example, by increasing X and Y radius slightly if the given endpoints are slightly too far apart). Note that this means this function is dangerous to use for 180 degree arcs, since then slight numerical roundoff can mean the difference between a solution being found and not - for 180 degree arcs it is safer to use EllipticalArc2d.with instead.

Argument type used in fromEndpoints.

smallPositive : SweptAngle

Flag used as argument to fromEndpoints.

smallNegative : SweptAngle

Flag used as argument to fromEndpoints.

largePositive : SweptAngle

Flag used as argument to fromEndpoints.

largeNegative : SweptAngle

Flag used as argument to fromEndpoints.

Properties

startAngle : EllipticalArc2d -> Float

The start angle of an elliptical arc is the value of the ellipse parameter at the start point of the arc.

EllipticalArc2d.startAngle exampleArc
--> 0
sweptAngle : EllipticalArc2d -> Float

The swept angle of an elliptical arc is the difference between values of the ellipse parameter at the start and end points of the arc.

EllipticalArc2d.sweptAngle exampleArc
--> degrees 90
startPoint : EllipticalArc2d -> Point2d

Get the start point of an elliptical arc.

EllipticalArc2d.startPoint exampleArc
--> Point2d.fromCoordinates ( 2, 0 )
endPoint : EllipticalArc2d -> Point2d

Get the end point of an elliptical arc.

EllipticalArc2d.endPoint exampleArc
--> Point2d.fromCoordinates ( 0, 1 )

All remaining properties of elliptical arcs are actually just properties of the underlying ellipse; check out the Ellipse2d module for details.

centerPoint : EllipticalArc2d -> Point2d
axes : EllipticalArc2d -> Frame2d
xAxis : EllipticalArc2d -> Axis2d
yAxis : EllipticalArc2d -> Axis2d
xDirection : EllipticalArc2d -> Direction2d
yDirection : EllipticalArc2d -> Direction2d
xRadius : EllipticalArc2d -> Float
yRadius : EllipticalArc2d -> Float

Evaluation

pointOn : EllipticalArc2d -> Float -> Point2d

Get a point along an elliptical arc, based on a parameter that ranges from 0 to 1. A parameter value of 0 corresponds to the start point of the arc and a value of 1 corresponds to the end point.

EllipticalArc2d.pointOn exampleArc 0
--> Point2d.fromCoordinates ( 2, 0 )


EllipticalArc2d.pointOn exampleArc 0.5
--> Point2d.fromCoordinates ( 1.4142, 0.7071 )


EllipticalArc2d.pointOn exampleArc 1
--> Point2d.fromCoordinates ( 0, 1 )
derivative : EllipticalArc2d -> Float -> Vector2d

Get the deriative value at a point along an elliptical arc, based on a parameter that ranges from 0 to 1. A parameter value of 0 corresponds to the derivative at the start point of the arc and a value of 1 corresponds to the derivative at the end point.

EllipticalArc2d.derivative exampleArc 0
--> Vector2d.fromComponents ( 0, 1.5708 )


EllipticalArc2d.derivative exampleArc 0.5
--> Vector2d.fromComponents ( -2.2214, 1.1107 )


EllipticalArc2d.derivative exampleArc 1
--> Vector2d.fromComponents ( -3.1416, 0 )

Transformations

reverse : EllipticalArc2d -> EllipticalArc2d

Reverse the direction of an elliptical arc, so that the start point becomes the end point and vice versa. Does not change the shape of the arc or any properties of the underlying ellipse.

EllipticalArc2d.reverse exampleArc
--> EllipticalArc2d.with
-->     { centerPoint = Point2d.origin
-->     , xDirection = Direction2d.x
-->     , xRadius = 2
-->     , yRadius = 1
-->     , startAngle = degrees 90
-->     , sweptAngle = degrees -90
-->     }
scaleAbout : Point2d -> Float -> EllipticalArc2d -> EllipticalArc2d

Scale an elliptical arc about a given point by a given scale.

exampleArc
    |> EllipticalArc2d.scaleAbout Point2d.origin 3
--> EllipticalArc2d.with
-->     { centerPoint = Point2d.origin
-->     , xDirection = Direction2d.x
-->     , xRadius = 6
-->     , yRadius = 3
-->     , startAngle = 0
-->     , sweptAngle = degrees 90
-->     }
rotateAround : Point2d -> Float -> EllipticalArc2d -> EllipticalArc2d

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

exampleArc
    |> EllipticalArc2d.rotateAround Point2d.origin
        (degrees 180)
--> EllipticalArc2d.with
-->     { centerPoint = Point2d.origin
-->     , xDirection = Direction2d.negativeX
-->     , xRadius = 2
-->     , yRadius = 1
-->     , startAngle = 0
-->     , sweptAngle = degrees 90
-->     }
translateBy : Vector2d -> EllipticalArc2d -> EllipticalArc2d

Translate an elliptical arc by a given displacement.

exampleArc
    |> EllipticalArc2d.translateBy
        (Vector2d.fromComponents ( 2, 3 ))
--> EllipticalArc2d.with
-->     { centerPoint =
-->         Point2d.fromCoordinates ( 2, 3 )
-->     , xDirection = Direction2d.x
-->     , xRadius = 2
-->     , yRadius = 1
-->     , startAngle = 0
-->     , sweptAngle = degrees 90
-->     }
mirrorAcross : Axis2d -> EllipticalArc2d -> EllipticalArc2d

Mirror an elliptical arc across a given axis.

mirroredArc =
    exampleArc
        |> EllipticalArc2d.mirrorAcross Axis2d.y


EllipticalArc2d.startPoint mirroredArc
--> Point2d.fromCoordinates ( -2, 0 )


EllipticalArc2d.endPoint mirroredArc
--> Point2d.fromCoordinates ( 0, 1 )

Coordinate conversions

relativeTo : Frame2d -> EllipticalArc2d -> EllipticalArc2d

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

localFrame =
    Frame2d.atPoint (Point2d.fromCoordinates ( 1, 2 ))


EllipticalArc2d.relativeTo localFrame exampleArc
--> EllipticalArc2d.with
-->     { centerPoint =
-->         Point2d.fromCoordinates ( -1, -2 )
-->     , xDirection = Direction2d.x
-->     , xRadius = 2
-->     , yRadius = 1
-->     , startAngle = 0
-->     , sweptAngle = degrees 90
-->     }
placeIn : Frame2d -> EllipticalArc2d -> EllipticalArc2d

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

localFrame =
    Frame2d.atPoint (Point2d.fromCoordinates ( 1, 2 ))


EllipticalArc2d.relativeTo localFrame exampleArc
--> EllipticalArc2d.with
-->     { centerPoint =
-->         Point2d.fromCoordinates ( 1, 2 )
-->     , xDirection = Direction2d.x
-->     , xRadius = 2
-->     , yRadius = 1
-->     , startAngle = 0
-->     , sweptAngle = degrees 90
-->     }

Arc length parameterization

An elliptical arc that has been parameterized by arc length.

arcLengthParameterized : Float -> EllipticalArc2d -> ArcLengthParameterized

Build an arc length parameterization of the given elliptical arc, within a given tolerance. Generally speaking, all operations on the resulting ArcLengthParameterized value will be accurate to within the given arc length tolerance.

tolerance =
    1.0e-4


parameterizedArc =
    EllipticalArc2d.arcLengthParameterized
        tolerance
        exampleArc
arcLength : ArcLengthParameterized -> Float

Find the total arc length of an elliptical arc. This will be accurate to within the tolerance given when calling arcLengthParameterized.

arcLength : Float
arcLength =
    EllipticalArc2d.arcLength parameterizedArc


arcLength
--> 2.4221
pointAlong : ArcLengthParameterized -> Float -> Maybe Point2d

Try to get the point along an elliptical arc at a given arc length. For example, to get the true midpoint of exampleArc:

EllipticalArc2d.pointAlong parameterizedArc
    (arcLength / 2)
--> Just (Point2d.fromCoordinates ( 1.1889, 0.8041 ))

Note that this is not the same as evaulating at a parameter value of 0.5:

EllipticalArc2d.pointOn exampleArc 0.5
--> Point2d.fromCoordinates ( 1.4142, 0.7071 )

If the given arc length is less than zero or greater than the arc length of the arc, Nothing is returned.

tangentAlong : ArcLengthParameterized -> Float -> Maybe Direction2d

Try to get the tangent direction along an elliptical arc at a given arc length. To get the tangent direction at the midpoint of exampleArc:

EllipticalArc2d.tangentAlong parameterizedArc
    (arcLength / 2)
--> Just (Direction2d.fromAngle (degrees 159.71))

If the given arc length is less than zero or greater than the arc length of the arc (or if the derivative of the arc happens to be exactly zero at the given arc length), Nothing is returned.

arcLengthToParameterValue : ArcLengthParameterized -> Float -> Maybe Float

Try to get the parameter value along an elliptical arc at a given arc length. If the given arc length is less than zero or greater than the arc length of the arc, returns Nothing.

EllipticalArc2d.arcLengthToParameterValue
    parameterizedArc
    (arcLength / 2)
--> Just 0.5947
parameterValueToArcLength : ArcLengthParameterized -> Float -> Maybe Float

Get the arc length along an elliptical arc at a given parameter value. If the given parameter value is less than zero or greater than one, returns Nothing.

EllipticalArc2d.parameterValueToArcLength
    parameterizedArc
    0.5
--> Just 0.9657

Low level

Low level functionality that you are unlikely to need to use directly.

derivativeMagnitude : EllipticalArc2d -> Float -> Float
maxSecondDerivativeMagnitude : EllipticalArc2d -> Float