opensolid/geometry/2.0.0

NOTE: this package is not compatible with Elm 0.19.1

OpenSolid.Arc2d

Arc2d

An Arc2d is a section of a circle, defined by its center point, start point and swept angle (the counterclockwise angle from the start point to the end point). This module includes functionality for

  • Constructing arcs through given points and/or with a given radius
  • Scaling, rotating, translating and mirroring arcs
  • Converting arcs between different coordinate systems
type alias Arc2d =
Arc2d

Constructors

{ centerPoint : Point2d
, startPoint : Point2d
, sweptAngle : Float
}
-> Arc2d

Construct an arc from its center point, start point, and swept angle:

exampleArc =
    Arc2d.with
        { centerPoint =
            Point2d.fromCoordinates ( 1, 1 )
        , startPoint =
            Point2d.fromCoordinates ( 3, 1 )
        , sweptAngle = degrees 90
        }


Arc2d.endPoint exampleArc
--> Point2d.fromCoordinates ( 1, 3 )

A positive swept angle means that the arc is formed by rotating the start point counterclockwise around the center point. A negative swept angle results in a clockwise arc instead.

throughPoints : ( Point2d, Point2d, Point2d ) -> Maybe Arc2d

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.

Arc2d.throughPoints
    ( Point2d.origin
    , Point2d.fromCoordinates ( 1, 0 )
    , Point2d.fromCoordinates ( 0, 1 )
    )
--> Just
-->     (Arc2d.with
-->         { centerPoint =
-->             Point2d.fromCoordinates ( 0.5, 0.5 )
-->         , startPoint = Point2d.origin
-->         , sweptAngle = degrees 270
-->         }
-->     )


Arc2d.throughPoints
    ( Point2d.fromCoordinates ( 1, 0 )
    , Point2d.origin
    , Point2d.fromCoordinates ( 0, 1 )
    )
--> Just
-->     (Arc2d.with
-->         { centerPoint =
-->             Point2d.fromCoordinates ( 0.5, 0.5 )
-->         , startPoint =
-->             Point2d.fromCoordinates ( 1, 0 )
-->         , sweptAngle = degrees -180
-->         }
-->     )


Arc2d.throughPoints
    ( Point2d.origin
    , Point2d.fromCoordinates ( 1, 0 )
    , Point2d.fromCoordinates ( 2, 0 )
    )
--> Nothing


Arc2d.throughPoints
    ( Point2d.origin
    , Point2d.origin
    , Point2d.fromCoordinates ( 1, 0 )
    )
--> Nothing
{ startPoint : Point2d
, endPoint : Point2d
, radius : Float
, sweptAngle : SweptAngle
}
-> Maybe Arc2d

Attempt to construct an arc with the given start point, end point and radius. For any given valid set of start point, end point and radius, there are four possible results, so the sweptAngle argument is used to specify which arc to create:

  • Arc2d.smallPositive will result in a counterclockwise arc with a small swept angle (in the range 0..180 degrees)
  • Arc2d.smallNegative will result in a clockwise arc with a small swept angle (in the range -180..0 degrees)
  • Arc2d.largePositive will result in a counterclockwise arc with a large swept angle (in the range 180..360 degrees)
  • Arc2d.largeNegative will result in a clockwise arc with a large swept angle (in the range -360..-180 degrees)

For example:

p1 =
    Point2d.fromCoordinates ( 1, 0 )


p2 =
    Point2d.fromCoordinates ( 0, 1 )


Arc2d.fromEndpoints
    { startPoint = p1
    , endPoint = p2
    , radius = 1
    , sweptAngle = Arc2d.smallPositive
    }
--> Just
-->     (Arc2d.with
-->         { startPoint =
-->             Point2d.fromCoordinates ( 1, 0 )
-->         , centerPoint = Point2d.origin
-->         , sweptAngle = degrees 90
-->         }
-->     )


Arc2d.fromEndpoints
    { startPoint = p1
    , endPoint = p2
    , radius = 1
    , sweptAngle = Arc2d.smallNegative
    }
--> Just
-->     (Arc2d.with
-->         { startPoint =
-->             Point2d.fromCoordinates ( 1, 0 )
-->         , centerPoint =
-->             Point2d.fromCoordinates ( 1, 1 )
-->         , sweptAngle = degrees -90
-->         }
-->     )


Arc2d.fromEndpoints
    { startPoint = p1
    , endPoint = p2
    , radius = 1
    , sweptAngle = Arc2d.largePositive
    }
--> Just
-->     (Arc2d.with
-->         { startPoint =
-->             Point2d.fromCoordinates ( 1, 0 )
-->         , centerPoint =
-->             Point2d.fromCoordinates ( 1, 1 )
-->         , sweptAngle = degrees 270
-->         }
-->     )


Arc2d.fromEndpoints
    { startPoint = p1
    , endPoint = p2
    , radius = 1
    , sweptAngle = Arc2d.largeNegative
    }
--> Just
-->     (Arc2d.with
-->         { startPoint =
-->             Point2d.fromCoordinates ( 1, 0 )
-->         , centerPoint = Point2d.origin
-->         , sweptAngle = degrees -270
-->         }
-->     )


Arc2d.fromEndpoints
    { startPoint = p1
    , endPoint = p2
    , radius = 2
    , sweptAngle = Arc2d.smallPositive
    }
--> Just
-->     (Arc2d.with
-->         { startPoint =
-->             Point2d.fromCoordinates ( 1, 0 )
-->         , centerPoint =
-->             Point2d.fromCoordinates
-->                 ( -0.8229
-->                 , -0.8229
-->                 )
-->         , sweptAngle = degrees 41.4096
-->         }
-->     )

If the start and end points are coincident or the distance between them is more than twice the given radius, returns Nothing:

Arc2d.fromEndpoints
    { startPoint = p1
    , endPoint = p2
    , radius = 0.5 -- too small!
    , sweptAngle = Arc2d.smallPositive
    }
--> Nothing

Note that this means it is dangerous to use this function to construct 180 degree arcs (half circles), since in this case due to numerical roundoff the distance between the two given points may appear to be slightly more than twice the given radius. In this case it is safer to use a more specialized approach, such as

halfCircle =
    Arc2d.with
        { startPoint = firstPoint
        , centerPoint =
            Point2d.midpoint firstPoint secondPoint
        , sweptAngle = degrees 180
        }

(Use sweptAngle = degrees -180 for a clockwise arc.)

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

centerPoint : Arc2d -> Point2d

Get the center point of an arc.

Arc2d.centerPoint exampleArc
--> Point2d.fromCoordinates ( 1, 1 )
radius : Arc2d -> Float

Get the radius of an arc.

Arc2d.radius exampleArc
--> 2
startPoint : Arc2d -> Point2d

Get the start point of an arc.

Arc2d.startPoint exampleArc
--> Point2d.fromCoordinates ( 3, 1 )
endPoint : Arc2d -> Point2d

Get the end point of an arc.

Arc2d.endPoint exampleArc
--> Point2d.fromCoordinates ( 1, 3 )
sweptAngle : Arc2d -> Float

Get the swept angle of an arc in radians.

Arc2d.sweptAngle exampleArc
--> 1.5708

The result will be positive for a counterclockwise arc and negative for a clockwise one.

Evaluation

pointOn : Arc2d -> Float -> Point2d

Get the point along an arc at a given parameter value. A parameter value of 0 corresponds to the start point of the arc and a value of 1 corresponds to the end point.

Arc2d.pointOn exampleArc 0.5
--> Point2d.fromCoordinates ( 2.4142, 2.4142 )
derivative : Arc2d -> Float -> Vector2d

Get the derivative of an arc with respect to a parameter that is 0 at the start point of the arc and 1 at the end point of the arc.

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


Arc2d.derivative exampleArc 1
--> Vector2d.fromComponents ( -3.1416, 0 )
evaluate : Arc2d -> Float -> ( Point2d, Vector2d )

Evaluate an arc at a given parameter value, returning the point on the arc at that parameter value and the derivative with respect to that parameter value.

Arc2d.evaluate exampleArc 0
--> ( Point2d.fromCoordinates ( 3, 1 )
--> , Vector2d.fromComponents ( 0, 3.1416 )
--> )


Arc2d.evaluate exampleArc 0.5
--> ( Point2d.fromCoordinates ( 2.4142, 2.4142 )
--> , Vector2d.fromComponents ( -2.2214, 2.2214 )
--> )


Arc2d.evaluate exampleArc 1
--> ( Point2d.fromCoordinates ( 1, 3 )
--> , Vector2d.fromComponents ( -3.1416, 0 )
--> )

Equivalent to (but more efficient than) calling pointOn and derivative separately.

Linear approximation

toPolyline : Float -> Arc2d -> Polyline2d

Approximate an arc as a polyline, within the specified tolerance.

Arc2d.toPolyline 0.1 exampleArc
--> Polyline2d.fromVertices
-->     [ Point2d.fromCoordinates ( 3, 1 )
-->     , Point2d.fromCoordinates ( 2.732, 2 )
-->     , Point2d.fromCoordinates ( 2, 2.732 )
-->     , Point2d.fromCoordinates ( 1, 3 )
-->     ]

A tolerance of zero will be treated as infinity (a single line segment will be returned).

Transformations

reverse : Arc2d -> Arc2d

Reverse the direction of an arc, so that the start point becomes the end point and vice versa.

Arc2d.reverse exampleArc
--> Arc2d.with
-->     { startPoint =
-->         Point2d.fromCoordinates ( 1, 3 )
-->     , centerPoint =
-->         Point2d.fromCoordinates ( 1, 1 )
-->     , sweptAngle = degrees -90
-->     }
scaleAbout : Point2d -> Float -> Arc2d -> Arc2d

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

point =
    Point2d.fromCoordinates ( 0, 1 )


Arc2d.scaleAbout point 2 exampleArc
--> Arc2d.with
-->     { startPoint =
-->         Point2d.fromCoordinates ( 6, 1 )
-->     , centerPoint =
-->         Point2d.fromCoordinates ( 2, 1 )
-->     , sweptAngle = degrees 90
-->     }
rotateAround : Point2d -> Float -> Arc2d -> Arc2d

Rotate an arc around a given point by a given angle.

Arc2d.rotateAround Point2d.origin (degrees 90)
--> Arc2d.with
-->     { startPoint =
-->         Point2d.fromCoordinates ( -1, 3 )
-->     , centerPoint =
-->         Point2d.fromCoordinates ( -1, 1 )
-->     , sweptAngle = degrees 90
-->     }
translateBy : Vector2d -> Arc2d -> Arc2d

Translate an arc by a given displacement.

displacement =
    Vector2d.fromComponents ( 2, 3 )


Arc2d.translateBy displacement exampleArc
--> Arc2d.with
-->     { startPoint =
-->         Point2d.fromCoordinates ( 5, 4 )
-->     , centerPoint =
-->         Point2d.fromCoordinates ( 3, 4 )
-->     , sweptAngle = degrees 90
-->     }
mirrorAcross : Axis2d -> Arc2d -> Arc2d

Mirror an arc across a given axis.

Arc2d.mirrorAcross Axis2d.y exampleArc
--> Arc2d.with
-->     { startPoint =
-->         Point2d.fromCoordinates ( -3, 1 )
-->     , centerPoint =
-->         Point2d.fromCoordinates ( -1, 1 )
-->     , sweptAngle = degrees -90
-->     }

Coordinate conversions

relativeTo : Frame2d -> Arc2d -> Arc2d

Take an 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 ))


Arc2d.relativeTo localFrame exampleArc
--> Arc2d.with
-->     { startPoint =
-->         Point2d.fromCoordinates ( 2, -1 )
-->     , centerPoint =
-->         Point2d.fromCoordinates ( 0, -1 )
-->     , sweptAngle = degrees 90
-->     }
placeIn : Frame2d -> Arc2d -> Arc2d

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 =
    Frame2d.atPoint (Point2d.fromCoordinates ( 1, 2 ))


Arc2d.placeIn localFrame exampleArc
--> Arc2d.with
-->     { startPoint =
-->         Point2d.fromCoordinates ( 4, 3 )
-->     , centerPoint =
-->         Point2d.fromCoordinates ( 2, 3 )
-->     , sweptAngle = degrees 90
-->     }