[
    {
        "name": "OpenSolid.Geometry.Encode",
        "comment": " JSON encoders for the core OpenSolid types.\n\n@docs vector2d, vector3d, direction2d, direction3d, point2d, point3d\n@docs axis2d, axis3d, plane3d, frame2d, frame3d, sketchPlane3d\n@docs lineSegment2d, lineSegment3d, triangle2d, triangle3d\n@docs interval, boundingBox2d, boundingBox3d\n@docs polyline2d, polyline3d, polygon2d\n@docs circle2d, circle3d, ellipse2d, arc2d, arc3d, ellipticalArc2d, sphere3d\n@docs quadraticSpline2d, quadraticSpline3d, cubicSpline2d, cubicSpline3d\n\n",
        "unions": [],
        "aliases": [],
        "values": [
            {
                "name": "arc2d",
                "comment": " Encode an `Arc2d` as an object with `centerPoint`, `startPoint` and\n`sweptAngle` fields.\n",
                "type": "Arc2d -> Value"
            },
            {
                "name": "arc3d",
                "comment": " Encode an `Arc3d` as an object with `axis`, `startPoint` and `sweptAngle`\nfields.\n",
                "type": "Arc3d -> Value"
            },
            {
                "name": "axis2d",
                "comment": " Encode an `Axis2d` as an object with `originPoint` and `direction` fields.\n",
                "type": "Axis2d -> Value"
            },
            {
                "name": "axis3d",
                "comment": " Encode an `Axis3d` as an object with `originPoint` and `direction` fields.\n",
                "type": "Axis3d -> Value"
            },
            {
                "name": "boundingBox2d",
                "comment": " Encode a `BoundingBox2d` as an object with `minX`, `maxX`, `minY` and `maxY`\nfields.\n",
                "type": "BoundingBox2d -> Value"
            },
            {
                "name": "boundingBox3d",
                "comment": " Encode a `BoundingBox3d` as an object with `minX`, `maxX`, `minY`, `maxY`,\n`minZ` and `maxZ` fields.\n",
                "type": "BoundingBox3d -> Value"
            },
            {
                "name": "circle2d",
                "comment": " Encode a `Circle2d` as an object with `centerPoint` and `radius` fields.\n",
                "type": "Circle2d -> Value"
            },
            {
                "name": "circle3d",
                "comment": " Encode a `Circle3d` as an object with `centerPoint`, `axialDirection` and\n`radius` fields.\n",
                "type": "Circle3d -> Value"
            },
            {
                "name": "cubicSpline2d",
                "comment": " Encode a `CubicSpline2d` as an array of four control points.\n",
                "type": "CubicSpline2d -> Value"
            },
            {
                "name": "cubicSpline3d",
                "comment": " Encode a `CubicSpline3d` as an array of four control points.\n",
                "type": "CubicSpline3d -> Value"
            },
            {
                "name": "direction2d",
                "comment": " Encode a `Direction2d` as an array of two floating-point components.\n",
                "type": "Direction2d -> Value"
            },
            {
                "name": "direction3d",
                "comment": " Encode a `Direction3d` as an array of three floating-point components.\n",
                "type": "Direction3d -> Value"
            },
            {
                "name": "ellipse2d",
                "comment": " Encode an `Ellipse2d` as an object with `centerPoint`, `xDirection`,\n`xRadius` and `yRadius` fields.\n",
                "type": "Ellipse2d -> Value"
            },
            {
                "name": "ellipticalArc2d",
                "comment": " Encode an `EllipticalArc2d` as an object with `centerPoint`, `xDirection`,\n`xRadius`, `yRadius`, `startAngle` and `sweptAngle` fields.\n",
                "type": "EllipticalArc2d -> Value"
            },
            {
                "name": "frame2d",
                "comment": " Encode a `Frame2d` as an object with `originPoint`, `xDirection` and\n`yDirection` fields.\n",
                "type": "Frame2d -> Value"
            },
            {
                "name": "frame3d",
                "comment": " Encode a `Frame3d` as an object with `originPoint`, `xDirection`,\n`yDirection` and `zDirection` fields.\n",
                "type": "Frame3d -> Value"
            },
            {
                "name": "interval",
                "comment": " Encode an `Interval` as an object with `minValue` and `maxValue` fields.\n",
                "type": "Interval -> Value"
            },
            {
                "name": "lineSegment2d",
                "comment": " Encode a `LineSegment2d` as an array of two endpoints.\n",
                "type": "LineSegment2d -> Value"
            },
            {
                "name": "lineSegment3d",
                "comment": " Encode a `LineSegment3d` as an array of two endpoints.\n",
                "type": "LineSegment3d -> Value"
            },
            {
                "name": "plane3d",
                "comment": " Encode a `Plane3d` as an object with `originPoint` and `normalDirection`\nfields.\n",
                "type": "Plane3d -> Value"
            },
            {
                "name": "point2d",
                "comment": " Encode a `Point2d` as an array of two floating-point coordinates.\n",
                "type": "Point2d -> Value"
            },
            {
                "name": "point3d",
                "comment": " Encode a `Point3d` as an array of three floating-point coordinates.\n",
                "type": "Point3d -> Value"
            },
            {
                "name": "polygon2d",
                "comment": " Encode a `Polygon2d` as an array of vertices.\n",
                "type": "Polygon2d -> Value"
            },
            {
                "name": "polyline2d",
                "comment": " Encode a `Polyline2d` as an array of vertices.\n",
                "type": "Polyline2d -> Value"
            },
            {
                "name": "polyline3d",
                "comment": " Encode a `Polyline3d` as an array of vertices.\n",
                "type": "Polyline3d -> Value"
            },
            {
                "name": "quadraticSpline2d",
                "comment": " Encode a `QuadraticSpline2d` as an array of three control points.\n",
                "type": "QuadraticSpline2d -> Value"
            },
            {
                "name": "quadraticSpline3d",
                "comment": " Encode a `QuadraticSpline3d` as an array of three control points.\n",
                "type": "QuadraticSpline3d -> Value"
            },
            {
                "name": "sketchPlane3d",
                "comment": " Encode a `SketchPlane3d` as an object with `originPoint`, `xDirection` and\n`yDirection` fields.\n",
                "type": "SketchPlane3d -> Value"
            },
            {
                "name": "sphere3d",
                "comment": " Encode a `Sphere` as an object with `centerPoint` and `radius` fields.\n",
                "type": "Sphere3d -> Value"
            },
            {
                "name": "triangle2d",
                "comment": " Encode a `Triangle2d` as an array of three vertices.\n",
                "type": "Triangle2d -> Value"
            },
            {
                "name": "triangle3d",
                "comment": " Encode a `Triangle3d` as an array of three vertices.\n",
                "type": "Triangle3d -> Value"
            },
            {
                "name": "vector2d",
                "comment": " Encode a `Vector2d` as an array of two floating-point components.\n",
                "type": "Vector2d -> Value"
            },
            {
                "name": "vector3d",
                "comment": " Encode a `Vector3d` as an array of three floating-point components.\n",
                "type": "Vector3d -> Value"
            }
        ],
        "binops": []
    },
    {
        "name": "OpenSolid.Geometry.Decode",
        "comment": " JSON decoders for the core OpenSolid types.\n\n@docs vector2d, vector3d, direction2d, direction3d, point2d, point3d\n@docs axis2d, axis3d, plane3d, frame2d, frame3d, sketchPlane3d\n@docs lineSegment2d, lineSegment3d, triangle2d, triangle3d\n@docs interval, boundingBox2d, boundingBox3d\n@docs polyline2d, polyline3d, polygon2d\n@docs circle2d, circle3d, ellipse2d, arc2d, arc3d, ellipticalArc2d, sphere3d\n@docs quadraticSpline2d, quadraticSpline3d, cubicSpline2d, cubicSpline3d\n\n",
        "unions": [],
        "aliases": [],
        "values": [
            {
                "name": "arc2d",
                "comment": " Decodes an `Arc2d` from an object with `centerPoint`, `startPoint` and\n`sweptAngle` fields.\n",
                "type": "Decoder Arc2d"
            },
            {
                "name": "arc3d",
                "comment": " Decodes an `Arc3d` from an object with `axis`, `startPoint` and `sweptAngle`\nfields.\n",
                "type": "Decoder Arc3d"
            },
            {
                "name": "axis2d",
                "comment": " Decodes an `Axis2d` from an object with `originPoint` and `direction`\nfields.\n",
                "type": "Decoder Axis2d"
            },
            {
                "name": "axis3d",
                "comment": " Decodes an `Axis3d` from an object with `originPoint` and `direction`\nfields.\n",
                "type": "Decoder Axis3d"
            },
            {
                "name": "boundingBox2d",
                "comment": " Decodes a `BoundingBox2d` from an object with `minX`, `maxX`, `minY` and\n`maxY` fields.\n",
                "type": "Decoder BoundingBox2d"
            },
            {
                "name": "boundingBox3d",
                "comment": " Decodes a `BoundingBox3d` from an object with `minX`, `maxX`, `minY`,\n`maxY`, `minZ` and `maxZ` fields.\n",
                "type": "Decoder BoundingBox3d"
            },
            {
                "name": "circle2d",
                "comment": " Decodes a `Circle2d` from an object with `centerPoint` and `radius` fields.\n",
                "type": "Decoder Circle2d"
            },
            {
                "name": "circle3d",
                "comment": " Decodes a `Circle3d` from an object with `centerPoint`, `axialDirection` and\n`radius` fields.\n",
                "type": "Decoder Circle3d"
            },
            {
                "name": "cubicSpline2d",
                "comment": " Decodes a `CubicSpline2d` from an array of four control points.\n",
                "type": "Decoder CubicSpline2d"
            },
            {
                "name": "cubicSpline3d",
                "comment": " Decodes a `CubicSpline3d` from an array of four control points.\n",
                "type": "Decoder CubicSpline3d"
            },
            {
                "name": "direction2d",
                "comment": " Decodes a `Direction2d` from an array of two floating-point components.\n",
                "type": "Decoder Direction2d"
            },
            {
                "name": "direction3d",
                "comment": " Decodes a `Direction3d` from an array of three floating-point components.\n",
                "type": "Decoder Direction3d"
            },
            {
                "name": "ellipse2d",
                "comment": " Decodes an `Ellipse2d` from an object with `centerPoint`, `xDirection`,\n`xRadius` and `yRadius` fields.\n",
                "type": "Decoder Ellipse2d"
            },
            {
                "name": "ellipticalArc2d",
                "comment": " Decodes an `EllipticalArc2d` from an object with `centerPoint`,\n`xDirection`, `xRadius`, `yRadius`, `startAngle` and `sweptAngle` fields.\n",
                "type": "Decoder EllipticalArc2d"
            },
            {
                "name": "frame2d",
                "comment": " Decodes a `Frame2d` from an object with `originPoint`, `xDirection` and\n`yDirection` fields.\n",
                "type": "Decoder Frame2d"
            },
            {
                "name": "frame3d",
                "comment": " Decodes a `Frame3d` from an object with `originPoint`, `xDirection`,\n`yDirection` and `zDirection` fields.\n",
                "type": "Decoder Frame3d"
            },
            {
                "name": "interval",
                "comment": " Decodes an `Interval` from an object with `minValue` and `maxValue` fields.\n",
                "type": "Decoder Interval"
            },
            {
                "name": "lineSegment2d",
                "comment": " Decodes a `LineSegment2d` from an array of two endpoints.\n",
                "type": "Decoder LineSegment2d"
            },
            {
                "name": "lineSegment3d",
                "comment": " Decodes a `LineSegment3d` from an array of two endpoints.\n",
                "type": "Decoder LineSegment3d"
            },
            {
                "name": "plane3d",
                "comment": " Decodes a `Plane3d` from an object with `originPoint` and `normalDirection`\nfields.\n",
                "type": "Decoder Plane3d"
            },
            {
                "name": "point2d",
                "comment": " Decodes a `Point2d` from an array of two floating-point coordinates.\n",
                "type": "Decoder Point2d"
            },
            {
                "name": "point3d",
                "comment": " Decodes a `Point3d` from an array of three floating-point coordinates.\n",
                "type": "Decoder Point3d"
            },
            {
                "name": "polygon2d",
                "comment": " Decodes a `Polygon2d` from an array of vertices.\n",
                "type": "Decoder Polygon2d"
            },
            {
                "name": "polyline2d",
                "comment": " Decodes a `Polyline2d` from an array of vertices.\n",
                "type": "Decoder Polyline2d"
            },
            {
                "name": "polyline3d",
                "comment": " Decodes a `Polyline3d` from an array of vertices.\n",
                "type": "Decoder Polyline3d"
            },
            {
                "name": "quadraticSpline2d",
                "comment": " Decodes a `QuadraticSpline2d` from an array of three control points.\n",
                "type": "Decoder QuadraticSpline2d"
            },
            {
                "name": "quadraticSpline3d",
                "comment": " Decodes a `QuadraticSpline3d` from an array of three control points.\n",
                "type": "Decoder QuadraticSpline3d"
            },
            {
                "name": "sketchPlane3d",
                "comment": " Decodes a `SketchPlane3d` from an object with `originPoint`, `xDirection`\nand `yDirection` fields.\n",
                "type": "Decoder SketchPlane3d"
            },
            {
                "name": "sphere3d",
                "comment": " Decodes a `Sphere3d` from an object with `centerPoint` and `radius` fields.\n",
                "type": "Decoder Sphere3d"
            },
            {
                "name": "triangle2d",
                "comment": " Decodes a `Triangle2d` from an array of three vertices.\n",
                "type": "Decoder Triangle2d"
            },
            {
                "name": "triangle3d",
                "comment": " Decodes a `Triangle3d` from an array of three vertices.\n",
                "type": "Decoder Triangle3d"
            },
            {
                "name": "vector2d",
                "comment": " Decodes a `Vector2d` from an array of two floating-point components.\n",
                "type": "Decoder Vector2d"
            },
            {
                "name": "vector3d",
                "comment": " Decodes a `Vector3d` from an array of three floating-point components.\n",
                "type": "Decoder Vector3d"
            }
        ],
        "binops": []
    },
    {
        "name": "OpenSolid.Arc3d",
        "comment": " <img src=\"https://opensolid.github.io/images/geometry/icons/arc3d.svg\" alt=\"Arc3d\" width=\"160\">\n\nAn `Arc3d` is a section of a circle in 3D, defined by its central axis,\nstart point and swept angle (the counterclockwise angle around the axis from the\nstart point to the arc's end point). This module includes functionality for\n\n  - Constructing arcs through given points\n  - Scaling, rotating, translating and mirroring arcs\n  - Converting arcs between different coordinate systems\n\n@docs Arc3d\n\n\n# Constructors\n\n@docs around, on, throughPoints\n\n\n# Properties\n\n@docs axialDirection, axis, centerPoint, radius, startPoint, endPoint, sweptAngle\n\n\n# Evaluation\n\n@docs pointOn, derivative, evaluate\n\n\n# Linear approximation\n\n@docs toPolyline\n\n\n# Transformations\n\n@docs reverse, scaleAbout, rotateAround, translateBy, mirrorAcross, projectInto\n\n\n# Coordinate conversions\n\n@docs relativeTo, placeIn\n\n",
        "unions": [],
        "aliases": [
            {
                "name": "Arc3d",
                "comment": " ",
                "args": [],
                "type": "Arc3d"
            }
        ],
        "values": [
            {
                "name": "around",
                "comment": " Construct an arc around the given axis, with the given start point and swept\nangle:\n\n    exampleArc =\n        Arc3d.around Axis3d.z\n            { startPoint =\n                Point3d.fromCoordinates ( 1, 1, 0 )\n            , sweptAngle = degrees 90\n            }\n\n    Arc3d.centerPoint exampleArc\n    --> Point3d.origin\n\n    Arc3d.endPoint exampleArc\n    --> Point3d.fromCoordinates ( -1, 1, 0 )\n\nPositive swept angles result in a counterclockwise (right-handed) rotation\naround the given axis and vice versa for negative swept angles. The center point\nof the returned arc will lie on the given axis.\n\n",
                "type": "Axis3d -> { startPoint : Point3d, sweptAngle : Float } -> Arc3d"
            },
            {
                "name": "axialDirection",
                "comment": " Get the axial direction of an arc.\n\n    Arc3d.axialDirection exampleArc\n    --> Direction3d.z\n\n",
                "type": "Arc3d -> Direction3d"
            },
            {
                "name": "axis",
                "comment": " Get the central axis of an arc. The origin point of the axis will be equal\nto the center point of the arc.\n\n    Arc3d.axis exampleArc\n    --> Axis3d.z\n\n",
                "type": "Arc3d -> Axis3d"
            },
            {
                "name": "centerPoint",
                "comment": " Get the center point of an arc.\n\n    Arc3d.centerPoint exampleArc\n    --> Point3d.origin\n\n",
                "type": "Arc3d -> Point3d"
            },
            {
                "name": "derivative",
                "comment": " Get the derivative of an arc with respect to a parameter that is 0 at the\nstart point of the arc and 1 at the end point of the arc.\n\n    Arc3d.derivative exampleArc 0\n    --> Vector3d.fromComponents ( -1.5708, 1.5708, 0 )\n\n    Arc3d.derivative exampleArc 1\n    --> Vector3d.fromComponents ( -1.5708, -1.5708, 0 )\n\n",
                "type": "Arc3d -> Float -> Vector3d"
            },
            {
                "name": "endPoint",
                "comment": " Get the end point of an arc.\n\n    Arc3d.endPoint exampleArc\n    --> Point3d.fromCoordinates ( -1, 1, 0 )\n\n",
                "type": "Arc3d -> Point3d"
            },
            {
                "name": "evaluate",
                "comment": " Evaluate an arc at a given parameter value, returning the point on the arc\nat that parameter value and the derivative with respect to that parameter value.\n\n    Arc3d.evaluate exampleArc 0\n    --> ( Point3d.fromCoordinates ( 1, 1, 0 )\n    --> , Vector3d.fromComponents ( -1.5708, 1.5708, 0 )\n    --> )\n\n    Arc3d.evaluate exampleArc 0.5\n    --> ( Point3d.fromCoordinates ( 1.4142, 0, 0 )\n    --> , Vector3d.fromComponents ( -2.2214, 0, 0 )\n    --> )\n\n    Arc3d.evaluate exampleArc 1\n    --> ( Point3d.fromCoordinates ( -1, 1, 0 )\n    --> , Vector3d.fromComponents ( -1.5708, -1.5708, 0 )\n    --> )\n\nEquivalent to (but more efficient than) calling `pointOn` and `derivative`\nseparately.\n\n",
                "type": "Arc3d -> Float -> ( Point3d, Vector3d )"
            },
            {
                "name": "mirrorAcross",
                "comment": " Mirror an arc across a given plane.\n\n    Arc3d.mirrorAcross Plane3d.xy exampleArc\n    --> Arc3d.around (Axis3d.flip Axis3d.z)\n    -->     { startPoint =\n    -->         Point3d.fromCoordinates ( 1, 1, 0 )\n    -->     , sweptAngle = degrees -90\n    -->     }\n\nNote that this flips the sign of the arc's swept angle.\n\n",
                "type": "Plane3d -> Arc3d -> Arc3d"
            },
            {
                "name": "on",
                "comment": " Construct a 3D arc lying _on_ a sketch plane by providing a 2D arc specified\nin XY coordinates _within_ the sketch plane.\n\n    arc =\n        Arc3d.on SketchPlane3d.xz <|\n            Arc2d.with\n                { centerPoint =\n                    Point2d.fromCoordinates ( 1, 1 )\n                , startPoint =\n                    Point2d.fromCoordinates ( 3, 1 )\n                , sweptAngle = degrees 90\n                }\n\n    Arc3d.centerPoint arc\n    --> Point3d.fromCoordinates ( 1, 0, 1 )\n\n    Arc3d.radius arc\n    --> 2\n\n    Arc3d.startPoint arc\n    --> Point3d.fromCoordinates ( 3, 0, 1 )\n\n    Arc3d.endPoint arc\n    --> Point3d.fromCoordinates ( 1, 0, 3 )\n\n",
                "type": "SketchPlane3d -> Arc2d -> Arc3d"
            },
            {
                "name": "placeIn",
                "comment": " Take an arc considered to be defined in local coordinates relative to a\ngiven reference frame, and return that arc expressed in global coordinates.\n\n    localFrame =\n        Frame3d.atPoint\n            (Point3d.fromCoordinates ( 1, 2, 3 ))\n\n    Arc3d.placeIn localFrame exampleArc\n    --> Arc3d.around\n    -->     (Axis3d.with\n    -->         { originPoint =\n    -->             Point3d.fromCoordinates ( 1, 2, 3 )\n    -->         , direction = Direction3d.z\n    -->         }\n    -->     )\n    -->     { startPoint =\n    -->         Point3d.fromCoordinates ( 2, 3, 3 )\n    -->     , sweptAngle = degrees 90\n    -->     }\n\n",
                "type": "Frame3d -> Arc3d -> Arc3d"
            },
            {
                "name": "pointOn",
                "comment": " Get the point along an arc at a given parameter value. A parameter value of\n0 corresponds to the start point of the arc and a value of 1 corresponds to the\nend point.\n\n    Arc3d.pointOn exampleArc 0.5\n    --> Point3d.fromCoordinates ( 0, 1.4142, 0 )\n\n",
                "type": "Arc3d -> Float -> Point3d"
            },
            {
                "name": "projectInto",
                "comment": " Project an arc into a sketch plane.\n\n    axis : Axis3d\n    axis =\n        Axis3d.with\n            { originPoint =\n                Point3d.fromCoordinates ( 1, 2, 3 )\n            , direction =\n                Direction3d.with\n                    { azimuth = 0\n                    , elevation = degrees 45\n                    }\n            }\n\n    arc : Arc3d\n    arc =\n        Arc3d.around axis\n            { startPoint =\n                Point3d.fromCoordinates ( 1, 4, 3 )\n            , sweptAngle = degrees 45\n            }\n\n    Arc3d.projectInto SketchPlane3d.xy arc\n    --> EllipticalArc2d.with\n    -->     { centerPoint =\n    -->         Point2d.fromCoordinates ( 1, 2 )\n    -->     , xDirection = Direction2d.y\n    -->     , xRadius = 2\n    -->     , yRadius = 1.4142\n    -->     , startAngle = degrees 0\n    -->     , sweptAngle = degrees 45\n    -->     }\n\n",
                "type": "SketchPlane3d -> Arc3d -> EllipticalArc2d"
            },
            {
                "name": "radius",
                "comment": " Get the radius of an arc.\n\n    Arc3d.radius exampleArc\n    --> 1.4142\n\n",
                "type": "Arc3d -> Float"
            },
            {
                "name": "relativeTo",
                "comment": " Take an arc defined in global coordinates, and return it expressed in local\ncoordinates relative to a given reference frame.\n\n    localFrame =\n        Frame3d.atPoint\n            (Point3d.fromCoordinates ( 1, 2, 3 ))\n\n    Arc3d.relativeTo localFrame exampleArc\n    --> Arc3d.around\n    -->     (Axis3d.with\n    -->         { originPoint = Point3d ( -1, -2, -3 )\n    -->         , direction = Direction3d.z\n    -->         }\n    -->     )\n    -->     { startPoint =\n    -->         Point3d.fromCoordinates ( 0, -1, -3 )\n    -->     , sweptAngle = degrees 90\n    -->     }\n\n",
                "type": "Frame3d -> Arc3d -> Arc3d"
            },
            {
                "name": "reverse",
                "comment": " Reverse the direction of an arc, so that the start point becomes the end\npoint and vice versa. The resulting arc will have the same axis as the original\nbut a swept angle with the opposite sign.\n\n    Arc3d.reverse exampleArc\n    --> Arc3d.around Axis3d.z\n    -->     { startPoint =\n    -->         Point3d.fromCoordinates ( -1, 1, 0 )\n    -->     , sweptAngle = degrees -90\n    -->     }\n\n",
                "type": "Arc3d -> Arc3d"
            },
            {
                "name": "rotateAround",
                "comment": " Rotate an arc around a given axis by a given angle (in radians).\n\n    Arc3d.rotateAround Axis3d.x (degrees 90) exampleArc\n    --> Arc3d.around (Axis3d.flip Axis3d.y)\n    -->     { startPoint =\n    -->         Point3d.fromCoordinates ( 1, 0, 1 )\n    -->     , sweptAngle = degrees 90\n    -->     }\n\n",
                "type": "Axis3d -> Float -> Arc3d -> Arc3d"
            },
            {
                "name": "scaleAbout",
                "comment": " Scale an arc about the given center point by the given scale.\n\n    point =\n        Point3d.fromCoordinates ( 0, -1, 0 )\n\n    Arc3d.scaleAbout point 2 exampleArc\n    --> Arc3d.around\n    -->     (Axis3d.with\n    -->         { originPoint =\n    -->             Point3d.fromCoordinates ( 0, 1, 0 )\n    -->         , direction = Direction3d.z\n    -->         }\n    -->     )\n    -->     { startPoint =\n    -->         Point3d.fromCoordinates ( 2, 3, 0 )\n    -->     , sweptAngle = degrees 90\n    -->     }\n\n",
                "type": "Point3d -> Float -> Arc3d -> Arc3d"
            },
            {
                "name": "startPoint",
                "comment": " Get the start point of an arc.\n\n    Arc3d.startPoint exampleArc\n    --> Point3d.fromCoordinates ( 1, 1, 0 )\n\n",
                "type": "Arc3d -> Point3d"
            },
            {
                "name": "sweptAngle",
                "comment": " Get the swept angle of an arc in radians.\n\n    Arc3d.sweptAngle exampleArc\n    --> 1.5708\n\nA positive swept angle means that the arc is formed by rotating the given start\npoint counterclockwise around the central axis, and vice versa for a negative\nangle.\n\n",
                "type": "Arc3d -> Float"
            },
            {
                "name": "throughPoints",
                "comment": " Attempt to construct an arc that starts at the first given point, passes\nthrough the second given point and ends at the third given point. If the three\npoints are collinear, returns `Nothing`.\n\n    p1 =\n        Point3d.fromCoordinates ( 0, 0, 1 )\n\n    p2 =\n        Point3d.origin\n\n    p3 =\n        Point3d.fromCoordinates ( 0, 1, 0 )\n\n    Arc3d.throughPoints ( p1, p2, p3 )\n    --> Just\n    -->     (Arc3d.on SketchPlane3d.yz <|\n    -->         Arc2d.with\n    -->             { centerPoint =\n    -->                 Point2d.fromCoordinates\n    -->                     ( 0.5, 0.5 )\n    -->             , startPoint =\n    -->                 Point3d.fromCoordinates ( 0, 1 )\n    -->             , sweptAngle = degrees 180\n    -->             }\n    -->     )\n\n",
                "type": "( Point3d, Point3d, Point3d ) -> Maybe Arc3d"
            },
            {
                "name": "toPolyline",
                "comment": " Approximate an arc as a polyline, within the specified tolerance.\n\n    Arc3d.toPolyline 0.1 exampleArc\n    --> Polyline3d.fromVertices\n    -->     [ Point3d.fromCoordinates ( 1, 1, 0 )\n    -->     , Point3d.fromCoordinates ( 0.366, 1.366, 0 )\n    -->     , Point3d.fromCoordinates ( -0.366, 1.366, 0 )\n    -->     , Point3d.fromCoordinates ( -1, 1, 0 )\n    -->     ]\n\nA tolerance of zero will be treated as infinity (a single line segment will be\nreturned).\n\n",
                "type": "Float -> Arc3d -> Polyline3d"
            },
            {
                "name": "translateBy",
                "comment": " Translate an arc by a given displacement.\n\n    displacement =\n        Vector3d.fromComponents ( 2, 1, 3 )\n\n    Arc3d.translateBy displacement exampleArc\n    --> Arc3d.around\n    -->     (Axis3d.with\n    -->         { originPoint = Point3d ( 2, 1, 3 )\n    -->         , direction = Direction3d.z\n    -->         }\n    -->     )\n    -->     { startPoint =\n    -->         Point3d.fromCoordinates ( 3, 2, 3 )\n    -->     , sweptAngle = degrees 90\n    -->     }\n\n",
                "type": "Vector3d -> Arc3d -> Arc3d"
            }
        ],
        "binops": []
    },
    {
        "name": "OpenSolid.Triangle3d",
        "comment": " <img src=\"https://opensolid.github.io/images/geometry/icons/triangle3d.svg\" alt=\"Triangle3d\" width=\"160\">\n\nA `Triangle3d` represents a triangle in 3D space, and is defined by its three\nvertices. This module contains triangle-related functionality such as:\n\n  - Finding the area and centroid of triangles\n  - Scaling, rotating, translating, mirroring and projecting triangles\n  - Converting triangles between different coordinate systems\n\n@docs Triangle3d\n\n\n# Constructors\n\n@docs fromVertices, on\n\n\n# Properties\n\n@docs vertices, edges, centroid, area, normalDirection, boundingBox, circumcircle\n\n\n# Transformations\n\nTransforming a triangle is equivalent to transforming its vertices.\n\n@docs scaleAbout, rotateAround, translateBy, mirrorAcross, projectOnto, mapVertices\n\n\n# Coordinate conversions\n\nFunctions for transforming triangles between local and global coordinates in\ndifferent coordinate frames.\n\n@docs relativeTo, placeIn, projectInto\n\n",
        "unions": [],
        "aliases": [
            {
                "name": "Triangle3d",
                "comment": " ",
                "args": [],
                "type": "Triangle3d"
            }
        ],
        "values": [
            {
                "name": "area",
                "comment": " Get the area of a triangle. This value is always positive.\n\n    Triangle3d.area exampleTriangle\n    --> 1.5811\n\n",
                "type": "Triangle3d -> Float"
            },
            {
                "name": "boundingBox",
                "comment": " Get the minimal bounding box containing a given triangle.\n\n    Triangle3d.boundingBox exampleTriangle\n    --> BoundingBox3d.with\n    -->     { minX = 1\n    -->     , maxX = 2\n    -->     , minY = 0\n    -->     , maxY = 1\n    -->     , minZ = 0\n    -->     , maxZ = 3\n    -->     }\n\n",
                "type": "Triangle3d -> BoundingBox3d"
            },
            {
                "name": "centroid",
                "comment": " Get the centroid (center of mass) of a triangle.\n\n    Triangle3d.centroid exampleTriangle\n    --> Point3d.fromCoordinates ( 1.6667, 0.6667, 1 )\n\n",
                "type": "Triangle3d -> Point3d"
            },
            {
                "name": "circumcircle",
                "comment": " Attempt to find the circumcircle of a triangle, a circle that passes through\neach of the triangle's vertices;\n\n    Triangle3d.circumcircle triangle\n\nis equivalent to\n\n    Circle3d.throughPoints (Triangle3d.vertices triangle)\n\nIf the triangle is degenerate (its three vertices are collinear), returns\n`Nothing`.\n\n",
                "type": "Triangle3d -> Maybe Circle3d"
            },
            {
                "name": "edges",
                "comment": " Get the edges of a triangle: from the first vertex to the second, from the\nsecond to the third, and from the third back to the first.\n\n    ( e1, e2, e3 ) =\n        Triangle3d.edges exampleTriangle\n\n\n    --> e1 =\n    -->     LineSegment3d.fromEndpoints\n    -->         ( Point3d.fromCoordinates ( 1, 0, 0 )\n    -->         , Point3d.fromCoordinates ( 2, 0, 0 )\n    -->         )\n    -->\n    --> e2 =\n    -->     LineSegment3d.fromEndpoints\n    -->         ( Point3d.fromCoordinates ( 2, 0, 0 )\n    -->         , Point3d.fromCoordinates ( 2, 1, 3 )\n    -->         )\n    -->\n    --> e3 =\n    -->     LineSegment3d.fromEndpoints\n    -->         ( Point3d.fromCoordinates ( 2, 1, 3 )\n    -->         , Point3d.fromCoordinates ( 1, 0, 0 )\n    -->         )\n\n",
                "type": "Triangle3d -> ( LineSegment3d, LineSegment3d, LineSegment3d )"
            },
            {
                "name": "fromVertices",
                "comment": " Construct a triangle from its three vertices:\n\n    exampleTriangle =\n        Triangle3d.fromVertices\n            ( Point3d.fromCoordinates ( 1, 0, 0 )\n            , Point3d.fromCoordinates ( 2, 0, 0 )\n            , Point3d.fromCoordinates ( 2, 1, 3 )\n            )\n\n",
                "type": "( Point3d, Point3d, Point3d ) -> Triangle3d"
            },
            {
                "name": "mapVertices",
                "comment": " Transform each vertex of a triangle by a given function and create a new\ntriangle from the resulting points. Most other transformation functions can be\ndefined in terms of `mapVertices`; for example,\n\n    Triangle3d.projectOnto plane\n\nis equivalent to\n\n    Triangle3d.mapVertices (Point3d.projectOnto plane)\n\n",
                "type": "(Point3d -> Point3d) -> Triangle3d -> Triangle3d"
            },
            {
                "name": "mirrorAcross",
                "comment": " Mirror a triangle across a given plane.\n\n    Triangle3d.mirrorAcross Plane3d.yz exampleTriangle\n    --> Triangle3d.fromVertices\n    -->     ( Point3d.fromCoordinates ( -1, 0, 0 )\n    -->     ( Point3d.fromCoordinates ( -2, 0, 0 )\n    -->     ( Point3d.fromCoordinates ( -2, 1, 3 )\n    -->     )\n\n",
                "type": "Plane3d -> Triangle3d -> Triangle3d"
            },
            {
                "name": "normalDirection",
                "comment": " Attempt to find the normal direction to a triangle. The resulting direction\nwill be oriented such that the triangle vertices are in counterclockwise order\naround it according to the right-hand rule. If the triangle is degenerate (its\nthree vertices are collinear), returns `Nothing`.\n\n    Triangle3d.normalDirection exampleTriangle\n    --> Just\n    -->    (Direction3d.with\n    -->        { azimuth = degrees -90\n    -->        , elevation = degrees 18.43\n    -->        }\n    -->    )\n\n",
                "type": "Triangle3d -> Maybe Direction3d"
            },
            {
                "name": "on",
                "comment": " Construct a 3D triangle lying _on_ a sketch plane by providing a 2D triangle\nspecified in XY coordinates _within_ the sketch plane.\n\n    Triangle3d.on SketchPlane3d.xz <|\n        Triangle2d.fromVertices\n            ( Point2d.fromCoordinates ( 1, 1 )\n            , Point2d.fromCoordinates ( 2, 1 )\n            , Point2d.fromCoordinates ( 1, 3 )\n            )\n    --> Triangle3d.fromVertices\n    -->     ( Point3d.fromCoordinates ( 1, 0, 1 )\n    -->     , Point3d.fromCoordinates ( 2, 0, 1 )\n    -->     , Point3d.fromCoordinates ( 1, 0, 3 )\n    -->     )\n\n",
                "type": "SketchPlane3d -> Triangle2d -> Triangle3d"
            },
            {
                "name": "placeIn",
                "comment": " Take a triangle considered to be defined in local coordinates relative to a\ngiven reference frame, and return that triangle expressed in global coordinates.\n\n    localFrame =\n        Frame3d.atPoint\n            (Point3d.fromCoordinates ( 2, 1, 3 ))\n\n    Triangle3d.placeIn localFrame exampleTriangle\n    --> Triangle3d.fromVertices\n    -->     ( Point3d.fromCoordinates ( 3, 1, 3 )\n    -->     , Point3d.fromCoordinates ( 4, 1, 3 )\n    -->     , Point3d.fromCoordinates ( 4, 2, 6 )\n    -->     )\n\n",
                "type": "Frame3d -> Triangle3d -> Triangle3d"
            },
            {
                "name": "projectInto",
                "comment": " Project a triangle into a given sketch plane. Conceptually, this finds the\n[orthographic projection](https://en.wikipedia.org/wiki/Orthographic_projection)\nof the triangle onto the plane and then expresses the projected triangle in 2D\nsketch coordinates.\n\n    Triangle3d.projectInto SketchPlane3d.xy exampleTriangle\n    --> Triangle2d.fromVertices\n    -->     ( Point2d.fromCoordinates ( 1, 0 )\n    -->     , Point2d.fromCoordinates ( 2, 0 )\n    -->     , Point2d.fromCoordinates ( 2, 1 )\n    -->     )\n\n    Triangle3d.projectInto SketchPlane3d.zx exampleTriangle\n    --> Triangle2d.fromVertices\n    -->     ( Point2d.fromCoordinates ( 0, 1 )\n    -->     , Point2d.fromCoordinates ( 0, 2 )\n    -->     , Point2d.fromCoordinates ( 3, 2 )\n    -->     )\n\n",
                "type": "SketchPlane3d -> Triangle3d -> Triangle2d"
            },
            {
                "name": "projectOnto",
                "comment": " Find the [orthographic projection](https://en.wikipedia.org/wiki/Orthographic_projection)\nof a triangle onto a plane.\n\n    Triangle3d.projectOnto Plane3d.xy exampleTriangle\n    --> Triangle3d.fromVertices\n    -->     ( Point3d.fromCoordinates ( 1, 0, 0 )\n    -->     , Point3d.fromCoordinates ( 2, 0, 0 )\n    -->     , Point3d.fromCoordinates ( 2, 1, 0 )\n    -->     )\n\n    Triangle3d.projectOnto Plane3d.xz exampleTriangle\n    --> Triangle3d.fromVertices\n    -->     ( Point3d.fromCoordinates ( 1, 0, 0 )\n    -->     , Point3d.fromCoordinates ( 2, 0, 0 )\n    -->     , Point3d.fromCoordinates ( 2, 0, 3 )\n    -->     )\n\n",
                "type": "Plane3d -> Triangle3d -> Triangle3d"
            },
            {
                "name": "relativeTo",
                "comment": " Take a triangle defined in global coordinates, and return it expressed\nin local coordinates relative to a given reference frame.\n\n    localFrame =\n        Frame3d.atPoint\n            (Point3d.fromCoordinates ( 2, 1, 3 ))\n\n    Triangle3d.relativeTo localFrame exampleTriangle\n    --> Triangle3d.fromVertices\n    -->     ( Point3d.fromCoordinates ( -1, -1, -3 )\n    -->     , Point3d.fromCoordinates ( 0, -1, -3 )\n    -->     , Point3d.fromCoordinates ( 0, 0, 0 )\n    -->     )\n\n",
                "type": "Frame3d -> Triangle3d -> Triangle3d"
            },
            {
                "name": "rotateAround",
                "comment": " Rotate a triangle around a given axis by a given angle (in radians).\n\n    exampleTriangle\n        |> Triangle3d.rotateAround Axis3d.z (degrees 90)\n    --> Triangle3d.fromVertices\n    -->     ( Point3d.fromCoordinates ( 0, 1, 0 )\n    -->     , Point3d.fromCoordinates ( 0, 2, 0 )\n    -->     , Point3d.fromCoordinates ( -1, 2, 3 )\n    -->     )\n\n",
                "type": "Axis3d -> Float -> Triangle3d -> Triangle3d"
            },
            {
                "name": "scaleAbout",
                "comment": " Scale a triangle about a given point by a given scale.\n\n    Triangle3d.scaleAbout Point3d.origin 2 exampleTriangle\n    --> Triangle3d.fromVertices\n    -->     ( Point3d.fromCoordinates ( 2, 0, 0 )\n    -->     , Point3d.fromCoordinates ( 4, 0, 0 )\n    -->     , Point3d.fromCoordinates ( 4, 2, 6 )\n    -->     )\n\n",
                "type": "Point3d -> Float -> Triangle3d -> Triangle3d"
            },
            {
                "name": "translateBy",
                "comment": " Translate a triangle by a given displacement.\n\n    displacement =\n        Vector3d.fromComponents ( 2, -1, 3 )\n\n    Triangle3d.translateBy displacement exampleTriangle\n    --> Triangle3d.fromVertices\n    -->     ( Point3d.fromCoordinates ( 3, -1, 3 )\n    -->     , Point3d.fromCoordinates ( 4, -1, 3 )\n    -->     , Point3d.fromCoordinates ( 4, 0, 6 )\n    -->     )\n\n",
                "type": "Vector3d -> Triangle3d -> Triangle3d"
            },
            {
                "name": "vertices",
                "comment": " Get the vertices of a triangle.\n\n    ( p1, p2, p3 ) =\n        Triangle3d.vertices exampleTriangle\n\n\n    --> p1 = Point3d.fromCoordinates ( 1, 0, 0 )\n    --> p2 = Point3d.fromCoordinates ( 2, 0, 0 )\n    --> p3 = Point3d.fromCoordinates ( 2, 1, 3 )\n\n",
                "type": "Triangle3d -> ( Point3d, Point3d, Point3d )"
            }
        ],
        "binops": []
    },
    {
        "name": "OpenSolid.Polyline3d",
        "comment": " <img src=\"https://opensolid.github.io/images/geometry/icons/polyline3d.svg\" alt=\"Polyline3d\" width=\"160\">\n\nA `Polyline3d` represents a sequence of vertices in 3D connected by line\nsegments. This module contains a variety of polyline-related functionality, such\nas\n\n  - Computing the length of polylines\n  - Scaling, rotating, translating and mirroring polylines\n  - Converting polylines between different coordinate systems\n\n@docs Polyline3d\n\n\n# Constructors\n\n@docs fromVertices, on\n\n\n# Properties\n\n@docs vertices, segments, length, boundingBox\n\n\n# Transformations\n\nTransforming a polyline is equivalent to transforming each of its vertices.\n\n@docs scaleAbout, rotateAround, translateBy, mirrorAcross, projectOnto, mapVertices\n\n\n# Coordinate conversions\n\n@docs relativeTo, placeIn, projectInto\n\n",
        "unions": [],
        "aliases": [
            {
                "name": "Polyline3d",
                "comment": " ",
                "args": [],
                "type": "Polyline3d"
            }
        ],
        "values": [
            {
                "name": "boundingBox",
                "comment": " Get the minimal bounding box containing a given polyline. Returns `Nothing`\nif the polyline has no vertices.\n\n    Polyline3d.boundingBox examplePolyline\n    --> Just\n    -->     (BoundingBox3d.with\n    -->         { minX = 0\n    -->         , maxX = 1\n    -->         , minY = 0\n    -->         , maxY = 2\n    -->         , minZ = 0\n    -->         , maxZ = 3\n    -->         }\n    -->     )\n\n",
                "type": "Polyline3d -> Maybe BoundingBox3d"
            },
            {
                "name": "fromVertices",
                "comment": " Construct a polyline from its vertices:\n\n    examplePolyline =\n        Polyline3d.fromVertices\n            [ Point2d.fromCoordinates ( 0, 0, 0 )\n            , Point2d.fromCoordinates ( 1, 0, 0 )\n            , Point2d.fromCoordinates ( 1, 2, 0 )\n            , Point2d.fromCoordinates ( 1, 2, 3 )\n            ]\n\n",
                "type": "List Point3d -> Polyline3d"
            },
            {
                "name": "length",
                "comment": " Get the overall length of a polyline (the sum of the lengths of its\nsegments).\n\n    Polyline3d.length examplePolyline\n    --> 6\n\n",
                "type": "Polyline3d -> Float"
            },
            {
                "name": "mapVertices",
                "comment": " Transform each vertex of a polyline by the given function. All other\ntransformations can be defined in terms of `mapVertices`; for example,\n\n    Polyline3d.mirrorAcross plane\n\nis equivalent to\n\n    Polyline3d.mapVertices (Point3d.mirrorAcross plane)\n\n",
                "type": "(Point3d -> Point3d) -> Polyline3d -> Polyline3d"
            },
            {
                "name": "mirrorAcross",
                "comment": " Mirror a polyline across the given plane.\n\n    Polyline3d.mirrorAcross Plane3d.xz examplePolyline\n    --> Polyline3d.fromVertices\n    -->     [ Point3d.fromCoordinates ( 0, 0, 0 )\n    -->     , Point3d.fromCoordinates ( 1, 0, 0 )\n    -->     , Point3d.fromCoordinates ( 1, -2, 0 )\n    -->     , Point3d.fromCoordinates ( 1, -2, 3 )\n    -->     ]\n\n",
                "type": "Plane3d -> Polyline3d -> Polyline3d"
            },
            {
                "name": "on",
                "comment": " Construct a 3D polyline lying _on_ a sketch plane by providing a 2D polyline\nspecified in XY coordinates _within_ the sketch plane.\n\n    Polyline3d.on SketchPlane3d.yz <|\n        Polyline2d.fromVertices\n            [ Point2d.fromCoordinates ( 0, 0 )\n            , Point2d.fromCoordinates ( 1, 0 )\n            , Point2d.fromCoordinates ( 1, 1 )\n            , Point2d.fromCoordinates ( 2, 1 )\n            ]\n    --> Polyline3d.fromVertices\n    -->     [ Point3d.fromCoordinates ( 0, 0, 0 )\n    -->     , Point3d.fromCoordinates ( 0, 1, 0 )\n    -->     , Point3d.fromCoordinates ( 0, 1, 1 )\n    -->     , Point3d.fromCoordinates ( 0, 2, 1 )\n    -->     ]\n\n",
                "type": "SketchPlane3d -> Polyline2d -> Polyline3d"
            },
            {
                "name": "placeIn",
                "comment": " Take a polyline considered to be defined in local coordinates relative\nto a given reference frame, and return that polyline expressed in global\ncoordinates.\n\n    localFrame =\n        Frame3d.atPoint\n            (Point3d.fromCoordinates ( 1, 2, 3 ))\n\n    Polyline3d.placeIn localFrame examplePolyline\n    --> Polyline3d.fromVertices\n    -->     [ Point3d.fromCoordinates ( 1, 2, 3 )\n    -->     , Point3d.fromCoordinates ( 2, 2, 3 )\n    -->     , Point3d.fromCoordinates ( 2, 4, 3 )\n    -->     , Point3d.fromCoordinates ( 2, 4, 6 )\n    -->     ]\n\n",
                "type": "Frame3d -> Polyline3d -> Polyline3d"
            },
            {
                "name": "projectInto",
                "comment": " Project a polyline into a given sketch plane. Conceptually, this finds the\n[orthographic projection](https://en.wikipedia.org/wiki/Orthographic_projection)\nof the polyline onto the plane and then expresses the projected polyline in 2D\nsketch coordinates.\n\n    Polyline3d.projectInto Plane3d.xy examplePolyline\n    --> Polyline2d.fromVertices\n    -->     [ Point2d.fromCoordinates ( 0, 0 )\n    -->     , Point2d.fromCoordinates ( 1, 0 )\n    -->     , Point2d.fromCoordinates ( 1, 2 )\n    -->     , Point2d.fromCoordinates ( 1, 2 )\n    -->     ]\n\n",
                "type": "SketchPlane3d -> Polyline3d -> Polyline2d"
            },
            {
                "name": "projectOnto",
                "comment": " Find the [orthographic projection](https://en.wikipedia.org/wiki/Orthographic_projection)\nof a polyline onto a plane. This will flatten the polyline.\n\n    Polyline3d.projectOnto Plane3d.xz examplePolyline\n    --> Polyline3d.fromVertices\n    -->     [ Point3d.fromCoordinates ( 0, 0, 0 )\n    -->     , Point3d.fromCoordinates ( 1, 0, 0 )\n    -->     , Point3d.fromCoordinates ( 1, 0, 0 )\n    -->     , Point3d.fromCoordinates ( 1, 0, 3 )\n    -->     ]\n\n",
                "type": "Plane3d -> Polyline3d -> Polyline3d"
            },
            {
                "name": "relativeTo",
                "comment": " Take a polyline defined in global coordinates, and return it expressed\nin local coordinates relative to a given reference frame.\n\n    localFrame =\n        Frame3d.atPoint\n            (Point3d.fromCoordinates ( 1, 2, 3 ))\n\n    Polyline3d.relativeTo localFrame examplePolyline\n    --> Polyline3d.fromVertices\n    -->     [ Point3d.fromCoordinates ( -1, -2, -3 )\n    -->     , Point3d.fromCoordinates ( 0, -2, -3 )\n    -->     , Point3d.fromCoordinates ( 0, 0, -3 )\n    -->     , Point3d.fromCoordinates ( 0, 0, 0 )\n    -->     ]\n\n",
                "type": "Frame3d -> Polyline3d -> Polyline3d"
            },
            {
                "name": "rotateAround",
                "comment": " Rotate a polyline around the given axis by the given angle (in radians).\n\n    examplePolyline\n        |> Polyline3d.rotateAround Axis3d.z (degrees 90)\n    --> Polyline3d.fromVertices\n    -->     [ Point3d.fromCoordinates ( 0, 0, 0 )\n    -->     , Point3d.fromCoordinates ( 0, 1, 0 )\n    -->     , Point3d.fromCoordinates ( -2, 1, 0 )\n    -->     , Point3d.fromCoordinates ( -2, 1, 3 )\n    -->     ]\n\n",
                "type": "Axis3d -> Float -> Polyline3d -> Polyline3d"
            },
            {
                "name": "scaleAbout",
                "comment": " Scale a polyline about the given center point by the given scale.\n\n    point =\n        Point3d.fromCoordinates ( 1, 0, 0 )\n\n    Polyline3d.scaleAbout point 2 examplePolyline\n    --> Polyline3d.fromVertices\n    -->     [ Point3d.fromCoordinates ( -1, 0, 0 )\n    -->     , Point3d.fromCoordinates ( 1, 0, 0 )\n    -->     , Point3d.fromCoordinates ( 1, 4, 0 )\n    -->     , Point3d.fromCoordinates ( 1, 4, 6 )\n    -->     ]\n\n",
                "type": "Point3d -> Float -> Polyline3d -> Polyline3d"
            },
            {
                "name": "segments",
                "comment": " Get the individual segments of a polyline.\n\n    Polyline3d.segments examplePolyline\n    --> [ LineSegment3d.fromEndpoints\n    -->     ( Point3d.fromCoordinates ( 0, 0, 0 )\n    -->     , Point3d.fromCoordinates ( 1, 0, 0 )\n    -->     )\n    --> , LineSegment3d.fromEndpoints\n    -->     ( Point3d.fromCoordinates ( 1, 0, 0 )\n    -->     , Point3d.fromCoordinates ( 1, 2, 0 )\n    -->     )\n    --> , LineSegment3d.fromEndpoints\n    -->     ( Point3d.fromCoordinates ( 1, 2, 0 )\n    -->     , Point3d.fromCoordinates ( 1, 2, 3 )\n    -->     )\n    --> ]\n\n",
                "type": "Polyline3d -> List LineSegment3d"
            },
            {
                "name": "translateBy",
                "comment": " Translate a polyline by the given displacement.\n\n    displacement =\n        Vector3d.fromComponents ( 1, 2, 3 )\n\n    Polyline3d.translateBy displacement examplePolyline\n    --> Polyline3d.fromVertices\n    -->     [ Point3d.fromCoordinates ( 1, 2, 3 )\n    -->     , Point3d.fromCoordinates ( 2, 2, 3 )\n    -->     , Point3d.fromCoordinates ( 2, 4, 3 )\n    -->     , Point3d.fromCoordinates ( 2, 4, 6 )\n    -->     ]\n\n",
                "type": "Vector3d -> Polyline3d -> Polyline3d"
            },
            {
                "name": "vertices",
                "comment": " Get the vertices of a polyline.\n\n    Polyline3d.vertices examplePolyline\n    --> [ Point3d.fromCoordinates ( 0, 0, 0 )\n    --> , Point3d.fromCoordinates ( 1, 0, 0 )\n    --> , Point3d.fromCoordinates ( 1, 2, 0 )\n    --> , Point3d.fromCoordinates ( 1, 2, 3 )\n    --> ]\n\n",
                "type": "Polyline3d -> List Point3d"
            }
        ],
        "binops": []
    },
    {
        "name": "OpenSolid.Sphere3d",
        "comment": " <img src=\"https://opensolid.github.io/images/geometry/icons/sphere3d.svg\" alt=\"Sphere3d\" width=\"160\">\n\nA `Sphere3d` is defined by its center point and radius. This module contains\nfunctionality for:\n\n  - Constructing spheres through points\n  - Scaling, rotating and translating spheres\n  - Extracting sphere properties like center point and volume\n\n@docs Sphere3d\n\n\n# Constants\n\n@docs unit\n\n\n# Constructors\n\n@docs with, throughPoints\n\n\n# Properties\n\n@docs centerPoint, radius, diameter, volume, surfaceArea, circumference, boundingBox\n\n\n# Queries\n\n@docs contains\n\n\n# Transformations\n\n@docs scaleAbout, rotateAround, translateBy, mirrorAcross, projectOnto, projectInto\n\n\n# Coordinate conversions\n\n@docs relativeTo, placeIn\n\n",
        "unions": [],
        "aliases": [
            {
                "name": "Sphere3d",
                "comment": " ",
                "args": [],
                "type": "Sphere3d"
            }
        ],
        "values": [
            {
                "name": "boundingBox",
                "comment": " Get the minimal bounding box containing a given sphere.\n\n    Sphere3d.boundingBox exampleSphere\n    --> BoundingBox3d.with\n    -->     { minX = -2\n    -->     , maxX = 4\n    -->     , minY = -1\n    -->     , maxY = 5\n    -->     , minZ = -2\n    -->     , maxZ = 4\n    -->     }\n\n",
                "type": "Sphere3d -> BoundingBox3d"
            },
            {
                "name": "centerPoint",
                "comment": " Get the center point of a sphere.\n\n    Sphere3d.centerPoint exampleSphere\n    --> Point3d.fromCoordinates ( 1, 2, 1 )\n\n",
                "type": "Sphere3d -> Point3d"
            },
            {
                "name": "circumference",
                "comment": " Get the circumference of a sphere (the circumference of a [great circle](https://en.wikipedia.org/wiki/Great_circle)\nof the sphere).\n\n    Sphere3d.circumference exampleSphere\n    --> 18.8496\n\n",
                "type": "Sphere3d -> Float"
            },
            {
                "name": "contains",
                "comment": " Check if a sphere contains a given point.\n\n    Sphere3d.contains\n        (Point3d.fromCoordinates ( 4, 2, 1 ))\n        exampleSphere\n    --> True\n\n    Sphere3d.contains\n        (Point3d.fromCoordinates ( 4.00001, 2, 1 ))\n        exampleSphere\n    --> False\n\n",
                "type": "Point3d -> Sphere3d -> Bool"
            },
            {
                "name": "diameter",
                "comment": " Get the diameter of a sphere.\n\n    Sphere3d.diameter exampleSphere\n    --> 6\n\n",
                "type": "Sphere3d -> Float"
            },
            {
                "name": "mirrorAcross",
                "comment": " Mirror a sphere across a given plane.\n\n    Sphere3d.mirrorAcross Plane3d.xy exampleSphere\n    --> Sphere3d.with\n    -->     { centerPoint =\n    -->         Point3d.fromCoordinates ( 1, 2, -1 )\n    -->     , radius = 3\n    -->     }\n\n",
                "type": "Plane3d -> Sphere3d -> Sphere3d"
            },
            {
                "name": "placeIn",
                "comment": " Take a sphere considered to be defined in local coordinates relative to a\ngiven reference frame, and return that sphere expressed in global coordinates.\n\n    localFrame : Frame3d\n    localFrame =\n        Frame3d.atPoint\n            (Point3d.fromCoordinates ( 1, 2, 3 ))\n\n    Sphere3d.placeIn localFrame exampleSphere\n    --> Sphere3d.with\n    -->     { centerPoint =\n    -->         Point3d.fromCoordinates ( 2, 4, 4 )\n    -->     , radius = 3\n    -->     }\n\n",
                "type": "Frame3d -> Sphere3d -> Sphere3d"
            },
            {
                "name": "projectInto",
                "comment": " Find the [orthographic projection](https://en.wikipedia.org/wiki/Orthographic_projection)\nof a sphere into a sketch plane.\n\n    Sphere3d.projectInto SketchPlane3d.xy exampleSphere\n    --> Circle2d.with\n    -->     { centerPoint =\n    -->         Point2d.fromCoordinates ( 1, 2 )\n    -->     , radius = 3.0\n    -->     }\n\n",
                "type": "SketchPlane3d -> Sphere3d -> Circle2d"
            },
            {
                "name": "projectOnto",
                "comment": " Find the [orthographic projection](https://en.wikipedia.org/wiki/Orthographic_projection)\nof a sphere onto a plane.\n\n    Sphere3d.projectOnto Plane3d.xy exampleSphere\n    --> Circle3d.with\n    -->     { centerPoint =\n    -->         Point3d.fromCoordinates ( 1, 2, 0 )\n    -->     , axialDirection = Direction3d.z\n    -->     , radius = 3.0\n    -->     }\n\n",
                "type": "Plane3d -> Sphere3d -> Circle3d"
            },
            {
                "name": "radius",
                "comment": " Get the radius of a sphere.\n\n    Sphere3d.radius exampleSphere\n    --> 3\n\n",
                "type": "Sphere3d -> Float"
            },
            {
                "name": "relativeTo",
                "comment": " Take a sphere defined in global coordinates, and return it expressed in\nlocal coordinates relative to a given reference frame.\n\n    localFrame : Frame3d\n    localFrame =\n        Frame3d.atPoint\n            (Point3d.fromCoordinates ( 1, 2, 3 ))\n\n    Sphere3d.relativeTo localFrame exampleSphere\n    --> Sphere3d.with\n    -->     { centerPoint =\n    -->         Point3d.fromCoordinates ( 0, 0, -2 )\n    -->     , radius = 3\n    -->     }\n\n",
                "type": "Frame3d -> Sphere3d -> Sphere3d"
            },
            {
                "name": "rotateAround",
                "comment": " Rotate a sphere around a given axis by a given angle (in radians).\n\n    exampleSphere\n        |> Sphere3d.rotateAround Axis3d.y (degrees 90)\n    --> Sphere3d.with\n    -->     { centerPoint =\n    -->         Point3d.fromCoordinates ( 1, 2, -1 )\n    -->     , radius = 3\n    -->     }\n\n",
                "type": "Axis3d -> Float -> Sphere3d -> Sphere3d"
            },
            {
                "name": "scaleAbout",
                "comment": " Scale a sphere around a given point by a given scale.\n\n    Sphere3d.scaleAbout Point3d.origin 3 exampleSphere\n    --> Sphere3d.with\n    -->     { centerPoint =\n    -->         Point3d.fromCoordinates ( 3, 6, 3 )\n    -->     , radius = 9\n    -->     }\n\n",
                "type": "Point3d -> Float -> Sphere3d -> Sphere3d"
            },
            {
                "name": "surfaceArea",
                "comment": " Get the surface area of a sphere.\n\n    Sphere3d.surfaceArea exampleSphere\n    --> 113.0973\n\n",
                "type": "Sphere3d -> Float"
            },
            {
                "name": "throughPoints",
                "comment": " Attempt to construct a sphere that passes through the four given points.\nReturns `Nothing` if four given points are coplanar.\n\n    Sphere3d.throughPoints\n        ( Point3d.fromCoordinates ( 1, 0, 0 )\n        , Point3d.fromCoordinates ( -1, 0, 0 )\n        , Point3d.fromCoordinates ( 0, 1, 0 )\n        , Point3d.fromCoordinates ( 0, 0, 0.5 )\n        )\n    --> Just <| Sphere3d.with\n        { centerPoint =\n            Point3d.fromCoordinates ( 0, 0, -0.75 )\n            , radius = 1.25\n            }\n\n    Sphere3d.throughPoints\n        ( Point3d.fromCoordinates ( 1, 0, 0 )\n        , Point3d.fromCoordinates ( -1, 0, 0 )\n        , Point3d.fromCoordinates ( 0, 1, 0 )\n        , Point3d.fromCoordinates ( 0, -1, 0 )\n        )\n    --> Nothing\n\n",
                "type": "( Point3d, Point3d, Point3d, Point3d ) -> Maybe Sphere3d"
            },
            {
                "name": "translateBy",
                "comment": " Translate a sphere by a given displacement.\n\n    displacement : Vector3d\n    displacement =\n        Vector3d.fromComponents ( 2, 1, 3 )\n\n    Sphere3d.translateBy displacement exampleSphere\n    --> Sphere3d.with\n    -->     { centerPoint =\n    -->         Point3d.fromCoordinates ( 3, 3, 4 )\n    -->     , radius = 3\n    -->     }\n\n",
                "type": "Vector3d -> Sphere3d -> Sphere3d"
            },
            {
                "name": "unit",
                "comment": " The unit sphere, centered on the origin with a radius of 1.\n\n    Sphere3d.unit\n    --> Sphere3d.with\n    -->     { centerPoint = Point3d.origin\n    -->     , radius = 1\n    -->     }\n\n",
                "type": "Sphere3d"
            },
            {
                "name": "volume",
                "comment": " Get the volume of a sphere.\n\n    Sphere3d.volume exampleSphere\n    --> 113.0973\n\n",
                "type": "Sphere3d -> Float"
            },
            {
                "name": "with",
                "comment": " Construct a sphere from its center point and radius:\n\n    exampleSphere =\n        Sphere3d.with\n            { centerPoint =\n                Point3d.fromCoordinates ( 1, 2, 1 )\n            , radius = 3\n            }\n\nA negative radius will be interpreted as positive (the absolute value will be\nused).\n\n",
                "type": "{ centerPoint : Point3d, radius : Float } -> Sphere3d"
            }
        ],
        "binops": []
    },
    {
        "name": "OpenSolid.CubicSpline3d",
        "comment": " <img src=\"https://opensolid.github.io/images/geometry/icons/cubicSpline3d.svg\" alt=\"CubicSpline3d\" width=\"160\">\n\nA `CubicSpline3d` is a cubic [Bézier curve](https://en.wikipedia.org/wiki/B%C3%A9zier_curve)\nin 3D defined by four control points. This module contains functionality for\n\n  - Evaluating points and derivatives along a spline\n  - Scaling, rotating, translating or mirroring a spline\n  - Converting a spline between local and global coordinates in different\n    reference frames\n\n@docs CubicSpline3d\n\n\n# Constructors\n\n@docs fromControlPoints, hermite, on, fromQuadraticSpline\n\n\n# Properties\n\n@docs controlPoints, startPoint, endPoint, startDerivative, endDerivative\n\n\n# Evaluation\n\n@docs pointOn, derivative, evaluate\n\n\n# Transformations\n\n@docs reverse, scaleAbout, rotateAround, translateBy, mirrorAcross, projectOnto\n\n\n# Coordinate conversions\n\n@docs relativeTo, placeIn, projectInto\n\n\n# Subdivision\n\n@docs bisect, splitAt\n\n\n# Arc length parameterization\n\n@docs ArcLengthParameterized, arcLengthParameterized, arcLength, pointAlong, tangentAlong, arcLengthToParameterValue, parameterValueToArcLength\n\n\n# Low level\n\nLow level functionality that you are unlikely to need to use directly.\n\n@docs derivativeMagnitude, maxSecondDerivativeMagnitude\n\n",
        "unions": [
            {
                "name": "ArcLengthParameterized",
                "comment": " A spline that has been parameterized by arc length.\n",
                "args": [],
                "cases": []
            }
        ],
        "aliases": [
            {
                "name": "CubicSpline3d",
                "comment": " ",
                "args": [],
                "type": "CubicSpline3d"
            }
        ],
        "values": [
            {
                "name": "arcLength",
                "comment": " Find the total arc length of a spline. This will be accurate to within the\ntolerance given when calling `arcLengthParameterized`.\n\n    arcLength : Float\n    arcLength =\n        CubicSpline3d.arcLength parameterizedSpline\n\n    arcLength\n    --> 4.3303\n\n",
                "type": "ArcLengthParameterized -> Float"
            },
            {
                "name": "arcLengthParameterized",
                "comment": " Build an arc length parameterization of the given spline, within\na given tolerance. Generally speaking, all operations on the resulting\n`ArcLengthParameterized` value will be accurate to within the given arc length\ntolerance.\n\n    tolerance =\n        1.0e-4\n\n    parameterizedSpline =\n        CubicSpline3d.arcLengthParameterized\n            tolerance\n            exampleSpline\n\n",
                "type": "Float -> CubicSpline3d -> ArcLengthParameterized"
            },
            {
                "name": "arcLengthToParameterValue",
                "comment": " Try to get the parameter value along a spline at a given arc length. If the\ngiven arc length is less than zero or greater than the arc length of the spline,\nreturns `Nothing`.\n\n    CubicSpline3d.arcLengthToParameterValue\n        parameterizedSpline\n        (arcLength / 4)\n    --> Just 0.2177\n\n",
                "type": "ArcLengthParameterized -> Float -> Maybe Float"
            },
            {
                "name": "bisect",
                "comment": " Split a spline into two roughly equal halves. Equivalent to `splitAt 0.5`.\n\n    CubicSpline3d.bisect exampleSpline\n    --> ( CubicSpline3d.fromControlPoints\n    -->     ( Point3d.fromCoordinates ( 1, 1, 1 )\n    -->     , Point3d.fromCoordinates ( 2, 1, 1 )\n    -->     , Point3d.fromCoordinates ( 2.5, 1.5, 1 )\n    -->     , Point3d.fromCoordinates ( 2.75, 2, 1.25 )\n    -->     )\n    --> , CubicSpline3d.fromControlPoints\n    -->     ( Point3d.fromCoordinates ( 2.75, 2, 1.25 )\n    -->     , Point3d.fromCoordinates ( 3, 2.5, 1.5 )\n    -->     , Point3d.fromCoordinates ( 3, 3, 2 )\n    -->     , Point3d.fromCoordinates ( 3, 3, 3 )\n    -->     )\n    --> )\n\n",
                "type": "CubicSpline3d -> ( CubicSpline3d, CubicSpline3d )"
            },
            {
                "name": "controlPoints",
                "comment": " Get the control points of a spline as a tuple.\n\n    ( p1, p2, p3, p4 ) =\n        CubicSpline3d.controlPoints exampleSpline\n\n\n    --> p1 = Point3d.fromCoordinates ( 1, 1, 1 )\n    --> p2 = Point3d.fromCoordinates ( 3, 1, 1 )\n    --> p3 = Point3d.fromCoordinates ( 3, 3, 1 )\n    --> p4 = Point3d.fromCoordinates ( 3, 3, 3 )\n\n",
                "type": "CubicSpline3d -> ( Point3d, Point3d, Point3d, Point3d )"
            },
            {
                "name": "derivative",
                "comment": " Get the deriative value at a point along a spline, based on a parameter that\nranges from 0 to 1. A parameter value of 0 corresponds to the start derivative\nof the spline and a value of 1 corresponds to the end derivative.\n\n    CubicSpline3d.derivative exampleSpline 0\n    --> Vector3d.fromComponents ( 6, 0, 0 )\n\n    CubicSpline3d.derivative exampleSpline 0.5\n    --> Vector3d.fromComponents ( 1.5, 3, 1.5 )\n\n    CubicSpline3d.derivative exampleSpline 1\n    --> Vector3d.fromComponents ( 0, 0, 6 )\n\nNote that the derivative interpolates linearly from end to end.\n\n",
                "type": "CubicSpline3d -> Float -> Vector3d"
            },
            {
                "name": "derivativeMagnitude",
                "comment": " Find the magnitude of the derivative to a spline at a particular parameter\nvalue;\n\n    CubicSpline3d.derivativeMagnitude spline t\n\nis equivalent to\n\n    Vector3d.length (CubicSpline3d.derivative spline t)\n\nbut more efficient since it avoids any intermediate `Vector3d` allocation.\n\n",
                "type": "CubicSpline3d -> Float -> Float"
            },
            {
                "name": "endDerivative",
                "comment": " Get the end derivative of a spline. This is equal to three times the vector\nfrom the spline's third control point to its fourth.\n\n    CubicSpline3d.endDerivative exampleSpline\n    --> Vector3d.fromComponents ( 0, 0, 6 )\n\n",
                "type": "CubicSpline3d -> Vector3d"
            },
            {
                "name": "endPoint",
                "comment": " Get the end point of a spline. This is equal to the spline's last control\npoint.\n\n    CubicSpline3d.endPoint exampleSpline\n    --> Point3d.fromCoordinates ( 3, 3, 3 )\n\n",
                "type": "CubicSpline3d -> Point3d"
            },
            {
                "name": "evaluate",
                "comment": " Evaluate a spline at a given parameter value, returning the point on the\nspline at that parameter value and the derivative with respect to that parameter\nvalue;\n\n    CubicSpline3d.evaluate spline t\n\nis equivalent to\n\n    ( CubicSpline3d.pointOn spline t\n    , CubicSpline3d.derivative spline t\n    )\n\nbut is more efficient.\n\n",
                "type": "CubicSpline3d -> Float -> ( Point3d, Vector3d )"
            },
            {
                "name": "fromControlPoints",
                "comment": " Construct a spline from its four control points:\n\n    exampleSpline =\n        CubicSpline3d.fromControlPoints\n            ( Point3d.fromCoordinates ( 1, 1, 1 )\n            , Point3d.fromCoordinates ( 3, 1, 1 )\n            , Point3d.fromCoordinates ( 3, 3, 1 )\n            , Point3d.fromCoordinates ( 3, 3, 3 )\n            )\n\n",
                "type": "( Point3d, Point3d, Point3d, Point3d ) -> CubicSpline3d"
            },
            {
                "name": "fromQuadraticSpline",
                "comment": " Convert a quadratic spline into the equivalent cubic spline (every quadratic\nspline can be represented exactly as a cubic spline).\n\n    quadraticSpline =\n        QuadraticSpline3d.fromControlPoints\n            ( Point3d.fromCoordinates ( 0, 0, 0  )\n            , Point3d.fromCoordinates ( 3, 0, 0 )\n            , Point3d.fromCoordinates ( 3, 3, 0 )\n            )\n\n    CubicSpline3d.fromQuadraticSpline quadraticSpline\n    --> CubicSpline3d.fromControlPoints\n    -->     ( Point3d.fromCoordinates ( 0, 0, 0 )\n    -->     , Point3d.fromCoordinates ( 2, 0, 0 )\n    -->     , Point3d.fromCoordinates ( 3, 1, 0 )\n    -->     , Point3d.fromCoordinates ( 3, 3, 0 )\n    -->     )\n\n",
                "type": "QuadraticSpline3d -> CubicSpline3d"
            },
            {
                "name": "hermite",
                "comment": " Construct a spline in Hermite form, from the position and derivative values\nat its start and end points, like so:\n\n![Hermite cubic spline](https://opensolid.github.io/images/geometry/1.2/hermiteCubicSpline.svg)\n\nThe spline is based on a parameter that ranges from 0 to 1; as a result, in most\ncases the length of each derivative vector should be roughly equal to the length\nof the resulting spline.\n\n",
                "type": "( Point3d, Vector3d ) -> ( Point3d, Vector3d ) -> CubicSpline3d"
            },
            {
                "name": "maxSecondDerivativeMagnitude",
                "comment": " Find an upper bound on the magnitude of the second derivative of a spline.\n",
                "type": "CubicSpline3d -> Float"
            },
            {
                "name": "mirrorAcross",
                "comment": " Mirror a spline across a plane.\n\n    CubicSpline3d.mirrorAcross Plane3d.xy exampleSpline\n    --> CubicSpline3d.fromControlPoints\n    -->     ( Point3d.fromCoordinates ( 1, 1, -1 )\n    -->     , Point3d.fromCoordinates ( 3, 1, -1 )\n    -->     , Point3d.fromCoordinates ( 3, 3, -1 )\n    -->     , Point3d.fromCoordinates ( 3, 3, -3 )\n    -->     )\n\n",
                "type": "Plane3d -> CubicSpline3d -> CubicSpline3d"
            },
            {
                "name": "on",
                "comment": " Construct a 3D spline lying _on_ a sketch plane by providing a 2D spline\nspecified in XY coordinates _within_ the sketch plane.\n\n    CubicSpline3d.on SketchPlane3d.xz <|\n        CubicSpline2d.fromControlPoints\n            ( Point2d.fromCoordinates ( 1, 1 )\n            , Point2d.fromCoordinates ( 3, 4 )\n            , Point2d.fromCoordinates ( 5, 1 )\n            , Point2d.fromCoordinates ( 7, 4 )\n            )\n    --> CubicSpline3d.fromControlPoints\n    -->     ( Point3d.fromCoordinates ( 1, 0, 1 )\n    -->     , Point3d.fromCoordinates ( 3, 0, 4 )\n    -->     , Point3d.fromCoordinates ( 5, 0, 1 )\n    -->     , Point3d.fromCoordinates ( 7, 0, 4 )\n    -->     )\n\n",
                "type": "SketchPlane3d -> CubicSpline2d -> CubicSpline3d"
            },
            {
                "name": "parameterValueToArcLength",
                "comment": " Try to get the arc length along a spline at a given parameter value. If the\ngiven parameter value is less than zero or greater than one, returns `Nothing`.\n\n    CubicSpline3d.parameterValueToArcLength\n        parameterizedSpline\n        0.25\n    --> Just 1.2163\n\n",
                "type": "ArcLengthParameterized -> Float -> Maybe Float"
            },
            {
                "name": "placeIn",
                "comment": " Take a spline considered to be defined in local coordinates relative to a\ngiven reference frame, and return that spline expressed in global coordinates.\n\n    localFrame =\n        Frame3d.atPoint\n            (Point3d.fromCoordinates ( 1, 2, 3 ))\n\n    CubicSpline3d.placeIn localFrame exampleSpline\n    --> CubicSpline3d.fromControlPoints\n    -->     ( Point3d.fromCoordinates ( 2, 3, 4 )\n    -->     , Point3d.fromCoordinates ( 4, 3, 4 )\n    -->     , Point3d.fromCoordinates ( 4, 5, 4 )\n    -->     , Point3d.fromCoordinates ( 4, 5, 6 )\n    -->     )\n\n",
                "type": "Frame3d -> CubicSpline3d -> CubicSpline3d"
            },
            {
                "name": "pointAlong",
                "comment": " Try to get the point along a spline at a given arc length. For example, to\nget the point a quarter of the way along `exampleSpline`:\n\n    CubicSpline3d.pointAlong parameterizedSpline\n        (arcLength / 4)\n    --> Just <|\n    -->     Point3d.fromCoordinates\n    -->         ( 2.0425, 1.2431, 1.0206 )\n\nNote that this is not the same as evaulating at a parameter value of 1/4:\n\n    CubicSpline3d.pointOn exampleSpline 0.25\n    --> Point3d.fromCoordinates ( 2.1563, 1.3125, 1.0313 )\n\nIf the given arc length is less than zero or greater than the arc length of the\nspline, `Nothing` is returned.\n\n",
                "type": "ArcLengthParameterized -> Float -> Maybe Point3d"
            },
            {
                "name": "pointOn",
                "comment": " Get a point along a spline, based on a parameter that ranges from 0 to 1. A\nparameter value of 0 corresponds to the start point of the spline and a value of\n1 corresponds to the end point.\n\n    CubicSpline3d.pointOn exampleSpline 0\n    --> Point3d.fromCoordinates ( 1, 1, 1 )\n\n    CubicSpline3d.pointOn exampleSpline 0.5\n    --> Point3d.fromCoordinates ( 2.75, 2, 1.25 )\n\n    CubicSpline3d.pointOn exampleSpline 1\n    --> Point3d.fromCoordinates ( 3, 3, 3 )\n\n",
                "type": "CubicSpline3d -> Float -> Point3d"
            },
            {
                "name": "projectInto",
                "comment": " Project a spline into a given sketch plane. Conceptually, this finds the\n[orthographic projection](https://en.wikipedia.org/wiki/Orthographic_projection)\nof the spline onto the plane and then expresses the projected spline in 2D\nsketch coordinates.\n\n    exampleSpline\n        |> CubicSpline3d.projectInto SketchPlane3d.yz\n    --> CubicSpline2d.fromControlPoints\n    -->     ( Point2d.fromCoordinates ( 1, 1 )\n    -->     , Point2d.fromCoordinates ( 1, 1 )\n    -->     , Point2d.fromCoordinates ( 3, 1 )\n    -->     , Point2d.fromCoordinates ( 3, 3 )\n    -->     )\n\n",
                "type": "SketchPlane3d -> CubicSpline3d -> CubicSpline2d"
            },
            {
                "name": "projectOnto",
                "comment": " Find the [orthographic projection](https://en.wikipedia.org/wiki/Orthographic_projection)\nof a spline onto a plane.\n\n    CubicSpline3d.projectOnto Plane3d.xy exampleSpline\n    --> CubicSpline3d.fromControlPoints\n    -->     ( Point3d.fromCoordinates ( 1, 1, 0 )\n    -->     , Point3d.fromCoordinates ( 3, 1, 0 )\n    -->     , Point3d.fromCoordinates ( 3, 3, 0 )\n    -->     , Point3d.fromCoordinates ( 3, 3, 0 )\n    -->     )\n\n",
                "type": "Plane3d -> CubicSpline3d -> CubicSpline3d"
            },
            {
                "name": "relativeTo",
                "comment": " Take a spline defined in global coordinates, and return it expressed in\nlocal coordinates relative to a given reference frame.\n\n    localFrame =\n        Frame3d.atPoint\n            (Point3d.fromCoordinates ( 1, 2, 3 ))\n\n    CubicSpline3d.relativeTo localFrame exampleSpline\n    --> CubicSpline3d.fromControlPoints\n    -->     ( Point3d.fromCoordinates ( 0, -1, -2 )\n    -->     , Point3d.fromCoordinates ( 2, -1, -2 )\n    -->     , Point3d.fromCoordinates ( 2, 1, -2 )\n    -->     , Point3d.fromCoordinates ( 2, 1, 0 )\n    -->     )\n\n",
                "type": "Frame3d -> CubicSpline3d -> CubicSpline3d"
            },
            {
                "name": "reverse",
                "comment": " Reverse a spline so that the start point becomes the end point, and vice\nversa.\n\n    CubicSpline3d.reverse exampleSpline\n    --> CubicSpline3d.fromControlPoints\n    -->     ( Point3d.fromCoordinates ( 3, 3, 3 )\n    -->     , Point3d.fromCoordinates ( 3, 3, 1 )\n    -->     , Point3d.fromCoordinates ( 3, 1, 1 )\n    -->     , Point3d.fromCoordinates ( 1, 1, 1 )\n    -->     )\n\n",
                "type": "CubicSpline3d -> CubicSpline3d"
            },
            {
                "name": "rotateAround",
                "comment": " Rotate a spline counterclockwise around a given axis by a given angle (in\nradians).\n\n    exampleSpline\n        |> CubicSpline3d.rotateAround Axis3d.z (degrees 90)\n    --> CubicSpline3d.fromControlPoints\n    -->     ( Point3d.fromCoordinates ( -1, 1, 1 )\n    -->     , Point3d.fromCoordinates ( -1, 3, 1 )\n    -->     , Point3d.fromCoordinates ( -3, 3, 1 )\n    -->     , Point3d.fromCoordinates ( -3, 3, 3 )\n    -->     )\n\n",
                "type": "Axis3d -> Float -> CubicSpline3d -> CubicSpline3d"
            },
            {
                "name": "scaleAbout",
                "comment": " Scale a spline about the given center point by the given scale.\n\n    CubicSpline3d.scaleAbout Point3d.origin 2 exampleSpline\n    --> CubicSpline3d.fromControlPoints\n    -->     ( Point3d.fromCoordinates ( 2, 2, 2 )\n    -->     , Point3d.fromCoordinates ( 6, 2, 2 )\n    -->     , Point3d.fromCoordinates ( 6, 6, 2 )\n    -->     , Point3d.fromCoordinates ( 6, 6, 6 )\n    -->     )\n\n",
                "type": "Point3d -> Float -> CubicSpline3d -> CubicSpline3d"
            },
            {
                "name": "splitAt",
                "comment": " Split a spline at a particular parameter value (in the range 0 to 1),\nresulting in two smaller splines.\n\n    CubicSpline3d.splitAt 0.75 exampleSpline\n    --> ( CubicSpline3d.fromControlPoints\n    -->     ( Point3d.fromCoordinates ( 1, 1, 1 )\n    -->     , Point3d.fromCoordinates ( 2.5, 1, 1 )\n    -->     , Point3d.fromCoordinates ( 2.88, 2.13, 1 )\n    -->     , Point3d.fromCoordinates ( 2.97, 2.69, 1.84 )\n    -->     )\n    --> , CubicSpline3d.fromControlPoints\n    -->     ( Point3d.fromCoordinates ( 2.97, 2.69, 1.84 )\n    -->     , Point3d.fromCoordinates ( 3, 2.88, 2.13 )\n    -->     , Point3d.fromCoordinates ( 3, 3, 2.5 )\n    -->     , Point3d.fromCoordinates ( 3, 3, 3 )\n    -->     )\n    --> )\n\n",
                "type": "Float -> CubicSpline3d -> ( CubicSpline3d, CubicSpline3d )"
            },
            {
                "name": "startDerivative",
                "comment": " Get the start derivative of a spline. This is equal to three times the\nvector from the spline's first control point to its second.\n\n    CubicSpline3d.startDerivative exampleSpline\n    --> Vector3d.fromComponents ( 6, 0, 0 )\n\n",
                "type": "CubicSpline3d -> Vector3d"
            },
            {
                "name": "startPoint",
                "comment": " Get the start point of a spline. This is equal to the spline's first control\npoint.\n\n    CubicSpline3d.startPoint exampleSpline\n    --> Point3d.fromCoordinates ( 1, 1, 1 )\n\n",
                "type": "CubicSpline3d -> Point3d"
            },
            {
                "name": "tangentAlong",
                "comment": " Try to get the tangent direction along a spline at a given arc length. To\nget the tangent direction a quarter of the way along `exampleSpline`:\n\n    CubicSpline3d.tangentAlong parameterizedSpline\n        (arcLength / 4)\n    --> Just <|\n    -->     Direction3d.with\n    -->         { azimuth = degrees 29.0995\n    -->         , elevation = degrees 3.8713\n    -->         }\n\nIf the given arc length is less than zero or greater than the arc length of the\nspline (or if the derivative of the spline happens to be exactly zero at the\ngiven arc length), `Nothing` is returned.\n\n",
                "type": "ArcLengthParameterized -> Float -> Maybe Direction3d"
            },
            {
                "name": "translateBy",
                "comment": " Translate a spline by a given displacement.\n\n    displacement =\n        Vector3d.fromComponents ( 2, 3, 1 )\n\n    CubicSpline3d.translateBy displacement exampleSpline\n    --> CubicSpline3d.fromControlPoints\n    -->     ( Point3d.fromCoordinates ( 3, 4, 2 )\n    -->     , Point3d.fromCoordinates ( 5, 4, 2 )\n    -->     , Point3d.fromCoordinates ( 5, 6, 2 )\n    -->     , Point3d.fromCoordinates ( 5, 6, 4 )\n    -->     )\n\n",
                "type": "Vector3d -> CubicSpline3d -> CubicSpline3d"
            }
        ],
        "binops": []
    },
    {
        "name": "OpenSolid.LineSegment3d",
        "comment": " <img src=\"https://opensolid.github.io/images/geometry/icons/lineSegment3d.svg\" alt=\"LineSegment3d\" width=\"160\">\n\nA `LineSegment3d` is a line between two points in 3D. This module contains\nfunctionality such as:\n\n  - Interpolating within a line segment or measuring its length\n  - Scaling, rotating, translating, mirroring or projecting a line segment\n  - Converting a line segment between local and global coordinates in different\n    reference frames\n\n@docs LineSegment3d\n\n\n# Constructors\n\n@docs fromEndpoints, from, along, on\n\n\n# Properties\n\n@docs startPoint, endPoint, endpoints, midpoint, length, squaredLength, direction, normalDirection, vector, boundingBox\n\n\n# Interpolation\n\n@docs interpolate\n\n\n# Transformations\n\nTransforming a line segment is equivalent to transforming its start and end\npoints and forming a new line segment between the resulting points.\n\n@docs reverse, scaleAbout, rotateAround, translateBy, mirrorAcross, projectOnto, mapEndpoints\n\n\n# Coordinate conversions\n\nFunctions for transforming line segments between local and global coordinates in\ndifferent coordinate frames.\n\n@docs relativeTo, placeIn, projectInto\n\n",
        "unions": [],
        "aliases": [
            {
                "name": "LineSegment3d",
                "comment": " ",
                "args": [],
                "type": "LineSegment3d"
            }
        ],
        "values": [
            {
                "name": "along",
                "comment": " Construct a line segment lying on the given axis, with its endpoints at the\ngiven distances from the axis' origin point.\n\n    LineSegment3d.along Axis3d.x 3 5\n    --> LineSegment3d.fromEndpoints\n    -->     ( Point3d.fromCoordinates ( 3, 0, 0 )\n    -->     , Point3d.fromCoordinates ( 5, 0, 0 )\n    -->     )\n\n    LineSegment3d.along Axis3d.y 2 -4\n    --> LineSegment3d.fromEndpoints\n    -->     ( Point3d.fromCoordinates ( 0, 2, 0 )\n    -->     , Point3d.fromCoordinates ( 0, -4, 0 )\n    -->     )\n\n",
                "type": "Axis3d -> Float -> Float -> LineSegment3d"
            },
            {
                "name": "boundingBox",
                "comment": " Get the minimal bounding box containing a line segment.\n\n    LineSegment3d.boundingBox exampleLineSegment\n    --> BoundingBox3d.with\n    -->     { minX = 1\n    -->     , maxX = 4\n    -->     , minY = 2\n    -->     , maxY = 5\n    -->     , minZ = 3\n    -->     , maxZ = 6\n    -->     }\n\n",
                "type": "LineSegment3d -> BoundingBox3d"
            },
            {
                "name": "direction",
                "comment": " Get the direction from a line segment's start point to its end point. If the\nline segment has zero length (the start and end points are the same), returns\n`Nothing`.\n\n    LineSegment3d.direction exampleLineSegment\n    --> Just\n    -->    (Direction3d.with\n    -->        { azimuth = degrees 45\n    -->        , elevation = degrees 35.26\n    -->        }\n    -->    )\n\n",
                "type": "LineSegment3d -> Maybe Direction3d"
            },
            {
                "name": "endPoint",
                "comment": " Get the end point of a line segment.\n\n    LineSegment3d.endPoint exampleLineSegment\n    --> Point3d.fromCoordinates ( 4, 5, 6 )\n\n",
                "type": "LineSegment3d -> Point3d"
            },
            {
                "name": "endpoints",
                "comment": " Get the endpoints of a line segment as a tuple.\n\n    ( p1, p2 ) =\n        LineSegment3d.endpoints lineSegment\n\n",
                "type": "LineSegment3d -> ( Point3d, Point3d )"
            },
            {
                "name": "from",
                "comment": " Construct a line segment from the first point to the second;\n\n    LineSegment3d.from firstPoint secondPoint\n\nis equivalent to\n\n    LineSegment3d.fromEndpoints ( firstPoint, secondPoint )\n\n",
                "type": "Point3d -> Point3d -> LineSegment3d"
            },
            {
                "name": "fromEndpoints",
                "comment": " Construct a line segment from its two endpoints:\n\n    exampleLineSegment =\n        LineSegment3d.fromEndpoints\n            ( Point3d.fromCoordinates ( 1, 2, 3 )\n            , Point3d.fromCoordinates ( 4, 5, 6 )\n            )\n\n",
                "type": "( Point3d, Point3d ) -> LineSegment3d"
            },
            {
                "name": "interpolate",
                "comment": " Interpolate a line segment between its start and end points; a value of 0.0\ncorresponds to the start point of the line segment, a value of 0.5 corresponds\nto its midpoint and a value of 1.0 corresponds to its end point. Values less\nthan 0.0 or greater than 1.0 can be used to extrapolate.\n\n    LineSegment3d.interpolate exampleLineSegment (1 / 3)\n    --> Point3d.fromCoordinates ( 2, 4, 5 )\n\n    LineSegment3d.interpolate exampleLineSegment (-1 / 3)\n    --> Point3d.fromCoordinates ( 0, 1, 2 )\n\n",
                "type": "LineSegment3d -> Float -> Point3d"
            },
            {
                "name": "length",
                "comment": " Get the length of a line segment.\n\n    LineSegment3d.length exampleLineSegment\n    --> 5.1962\n\n",
                "type": "LineSegment3d -> Float"
            },
            {
                "name": "mapEndpoints",
                "comment": " Transform the start and end points of a line segment by a given function\nand create a new line segment from the resulting points. Most other\ntransformation functions can be defined in terms of `mapEndpoints`; for example,\n\n    LineSegment3d.projectOnto plane\n\nis equivalent to\n\n    LineSegment3d.mapEndpoints (Point3d.projectOnto plane)\n\n",
                "type": "(Point3d -> Point3d) -> LineSegment3d -> LineSegment3d"
            },
            {
                "name": "midpoint",
                "comment": " Get the midpoint of a line segment.\n\n    LineSegment3d.midpoint exampleLineSegment\n    --> Point3d.fromCoordinates ( 2.5, 3.5, 4.5 )\n\n",
                "type": "LineSegment3d -> Point3d"
            },
            {
                "name": "mirrorAcross",
                "comment": " Mirror a line segment across a plane.\n\n    exampleLineSegment\n        |> LineSegment3d.mirrorAcross Plane3d.xy\n    --> LineSegment3d.fromEndpoints\n    -->     ( Point3d.fromCoordinates ( 1, 2, -3 )\n    -->     , Point3d.fromCoordinates ( 4, 5, -6 )\n    -->     )\n\n",
                "type": "Plane3d -> LineSegment3d -> LineSegment3d"
            },
            {
                "name": "normalDirection",
                "comment": " Get an arbitrary direction perpendicular to a line segment. If the line\nsegment has zero length, returns `Nothing`.\n\n    LineSegment3d.normalDirection exampleLineSegment\n    --> Just\n    -->    (Direction3d.with\n    -->        { azimuth = degrees -90\n    -->        , elevation = degrees 45\n    -->        }\n    -->    )\n\n",
                "type": "LineSegment3d -> Maybe Direction3d"
            },
            {
                "name": "on",
                "comment": " Construct a 3D line segment lying _on_ a sketch plane by providing a 2D line\nsegment specified in XY coordinates _within_ the sketch plane.\n\n    LineSegment3d.on SketchPlane3d.yz <|\n        LineSegment2d.fromEndpoints\n            ( Point2d.fromCoordinates ( 1, 2 )\n            , Point2d.fromCoordinates ( 3, 4 )\n            )\n    --> LineSegment3d.fromEndpoints\n    -->     ( Point3d.fromCoordinates ( 0, 1, 2 )\n    -->     , Point3d.fromCoordinates ( 0, 3, 4 )\n    -->     )\n\n",
                "type": "SketchPlane3d -> LineSegment2d -> LineSegment3d"
            },
            {
                "name": "placeIn",
                "comment": " Take a line segment considered to be defined in local coordinates relative\nto a given reference frame, and return that line segment expressed in global\ncoordinates.\n\n    localFrame =\n        Frame3d.atPoint\n            (Point3d.fromCoordinates ( 1, 2, 3 ))\n\n    LineSegment3d.placeIn localFrame exampleLineSegment\n    --> LineSegment3d.fromEndpoints\n    -->     ( Point3d.fromCoordinates ( 2, 4, 6 )\n    -->     , Point3d.fromCoordinates ( 5, 7, 9 )\n    -->     )\n\n",
                "type": "Frame3d -> LineSegment3d -> LineSegment3d"
            },
            {
                "name": "projectInto",
                "comment": " Project a line segment into a given sketch plane. Conceptually, this finds\nthe [orthographic projection](https://en.wikipedia.org/wiki/Orthographic_projection)\nof the line segment onto the plane and then expresses the projected line segment\nin 2D sketch coordinates.\n\n    exampleLineSegment\n        |> LineSegment3d.projectInto SketchPlane3d.xy\n    --> LineSegment2d.fromEndpoints\n    -->     ( Point2d.fromCoordinates ( 1, 2 )\n    -->     , Point2d.fromCoordinates ( 4, 5 )\n    -->     )\n\n    exampleLineSegment\n        |> LineSegment3d.projectInto SketchPlane3d.yz\n    --> LineSegment2d.fromEndpoints\n    -->     ( Point2d.fromCoordinates ( 2, 3 )\n    -->     , Point2d.fromCoordinates ( 5, 6 )\n    -->     )\n\n    exampleLineSegment\n        |> LineSegment3d.projectInto SketchPlane3d.zx\n    --> LineSegment2d.fromEndpoints\n    -->     ( Point2d.fromCoordinates ( 3, 1 )\n    -->     , Point2d.fromCoordinates ( 6, 4 )\n    -->     )\n\n",
                "type": "SketchPlane3d -> LineSegment3d -> LineSegment2d"
            },
            {
                "name": "projectOnto",
                "comment": " Find the [orthographic projection](https://en.wikipedia.org/wiki/Orthographic_projection)\nof a line segment onto a plane.\n\n    LineSegment3d.projectOnto Plane3d.yz exampleLineSegment\n    --> LineSegment3d.fromEndpoints\n    -->     ( Point3d.fromCoordinates ( 0, 2, 3 )\n    -->     , Point3d.fromCoordinates ( 0, 5, 6 )\n    -->     )\n\n",
                "type": "Plane3d -> LineSegment3d -> LineSegment3d"
            },
            {
                "name": "relativeTo",
                "comment": " Take a line segment defined in global coordinates, and return it expressed\nin local coordinates relative to a given reference frame.\n\n    localFrame =\n        Frame3d.atPoint\n            (Point3d.fromCoordinates ( 1, 2, 3 ))\n\n    LineSegment3d.relativeTo localFrame exampleLineSegment\n    --> LineSegment3d.fromEndpoints\n    -->     ( Point3d.fromCoordinates ( 0, 0, 0 )\n    -->     , Point3d.fromCoordinates ( 3, 3, 3 )\n    -->     )\n\n",
                "type": "Frame3d -> LineSegment3d -> LineSegment3d"
            },
            {
                "name": "reverse",
                "comment": " Reverse a line segment, swapping its start and end points.\n\n    LineSegment3d.reverse exampleLineSegment\n    --> LineSegment3d.fromEndpoints\n    -->     ( Point3d.fromCoordinates ( 4, 5, 6 )\n    -->     , Point3d.fromCoordinates ( 1, 2, 3 )\n    -->     )\n\n",
                "type": "LineSegment3d -> LineSegment3d"
            },
            {
                "name": "rotateAround",
                "comment": " Rotate a line segment around a given axis by a given angle (in radians).\n\n    exampleLineSegment\n        |> LineSegment3d.rotateAround Axis3d.z (degrees 90)\n    --> LineSegment3d.fromEndpoints\n    -->     ( Point3d.fromCoordinates ( -2, 1, 3 )\n    -->     , Point3d.fromCoordinates ( -5, 4, 6 )\n    -->     )\n\n",
                "type": "Axis3d -> Float -> LineSegment3d -> LineSegment3d"
            },
            {
                "name": "scaleAbout",
                "comment": " Scale a line segment about the given center point by the given scale.\n\n    point =\n        Point3d.fromCoordinates ( 1, 1, 1 )\n\n    LineSegment3d.scaleAbout point 2 exampleLineSegment\n    --> LineSegment3d.fromEndpoints\n    -->     ( Point3d.fromCoordinates ( 1, 3, 5 )\n    -->     , Point3d.fromCoordinates ( 7, 9, 11 )\n    -->     )\n\n",
                "type": "Point3d -> Float -> LineSegment3d -> LineSegment3d"
            },
            {
                "name": "squaredLength",
                "comment": " Get the squared length of a line segment. Slightly more efficient than\n`length` since it avoids a square root.\n\n    LineSegment3d.squaredLength exampleLineSegment\n    --> 27\n\n",
                "type": "LineSegment3d -> Float"
            },
            {
                "name": "startPoint",
                "comment": " Get the start point of a line segment.\n\n    LineSegment3d.startPoint exampleLineSegment\n    --> Point3d.fromCoordinates ( 1, 2, 3 )\n\n",
                "type": "LineSegment3d -> Point3d"
            },
            {
                "name": "translateBy",
                "comment": " Translate a line segment by a given displacement.\n\n    displacement =\n        Vector3d.fromComponents ( 1, 2, 3 )\n\n    exampleLineSegment\n        |> LineSegment3d.translateBy displacement\n    --> LineSegment3d.fromEndpoints\n    -->     ( Point3d.fromCoordinates ( 2, 4, 6 )\n    -->     , Point3d.fromCoordinates ( 5, 7, 9 )\n    -->     )\n\n",
                "type": "Vector3d -> LineSegment3d -> LineSegment3d"
            },
            {
                "name": "vector",
                "comment": " Get the vector from a line segment's start point to its end point.\n\n    LineSegment3d.vector exampleLineSegment\n    --> Vector3d.fromComponents ( 2, 2, 2 )\n\n",
                "type": "LineSegment3d -> Vector3d"
            }
        ],
        "binops": []
    },
    {
        "name": "OpenSolid.Circle3d",
        "comment": " <img src=\"https://opensolid.github.io/images/geometry/icons/circle3d.svg\" alt=\"Circle3d\" width=\"160\">\n\nA `Circle3d` is defined by its center point, axial direction and radius. The\naxial direction is the direction of the axis through the center of the circle\nthat all points on the circle are equidistant from, or equivalently the normal\ndirection of the plane defined by the circle. This module contains functionality\nfor:\n\n  - Constructing circles around axes, on planes, or through points\n  - Scaling, rotating and translating circles\n  - Extracting circle properties like center point and area\n\n@docs Circle3d\n\n\n# Constructors\n\n@docs with, around, on, throughPoints\n\n\n# Properties\n\n@docs centerPoint, axialDirection, radius, diameter, axis, plane, area, circumference, boundingBox\n\n\n# Transformations\n\n@docs scaleAbout, rotateAround, translateBy, mirrorAcross, projectInto\n\n\n# Coordinate conversions\n\n@docs relativeTo, placeIn\n\n",
        "unions": [],
        "aliases": [
            {
                "name": "Circle3d",
                "comment": " ",
                "args": [],
                "type": "Circle3d"
            }
        ],
        "values": [
            {
                "name": "area",
                "comment": " Get the area of a circle.\n\n    Circle3d.area exampleCircle\n    --> 28.2743\n\n",
                "type": "Circle3d -> Float"
            },
            {
                "name": "around",
                "comment": " Construct a circle around the given axis that passes through the given\npoint.\n\n    point =\n        Point3d.fromCoordinates ( 3, 0, 2 )\n\n    Circle3d.around Axis3d.z point\n    --> Circle3d.with\n    -->     { centerPoint =\n    -->         Point3d.fromCoordinates ( 0, 0, 2 )\n    -->     , axialDirection = Direction3d.z\n    -->     , radius = 3\n    -->     }\n\n",
                "type": "Axis3d -> Point3d -> Circle3d"
            },
            {
                "name": "axialDirection",
                "comment": " Get the axial direction of a circle.\n\n    Circle3d.axialDirection exampleCircle\n    --> Direction3d.z\n\n",
                "type": "Circle3d -> Direction3d"
            },
            {
                "name": "axis",
                "comment": " Get the central axis of a circle, perpendicular to its [`plane`](#plane).\nThe origin point of the returned axis will be the center point of the circle.\n\n    Circle3d.axis exampleCircle\n    --> Axis3d.with\n    -->     { originPoint =\n    -->         Point3d.fromCoordinates ( 2, 0, 1 )\n    -->     , direction = Direction3d.z\n    -->     }\n\n",
                "type": "Circle3d -> Axis3d"
            },
            {
                "name": "boundingBox",
                "comment": " Get the minimal bounding box containing a given circle.\n\n    Circle3d.boundingBox exampleCircle\n    --> BoundingBox3d.with\n    -->     { minX = -1\n    -->     , maxX = 5\n    -->     , minY = -3\n    -->     , maxY = 3\n    -->     , minZ = 1\n    -->     , maxZ = 1\n    -->     }\n\n",
                "type": "Circle3d -> BoundingBox3d"
            },
            {
                "name": "centerPoint",
                "comment": " Get the center point of a circle.\n\n    Circle3d.centerPoint exampleCircle\n    --> Point3d.fromCoordinates ( 2, 0, 1 )\n\n",
                "type": "Circle3d -> Point3d"
            },
            {
                "name": "circumference",
                "comment": " Get the circumference of a circle.\n\n    Circle3d.circumference exampleCircle\n    --> 18.8496\n\n",
                "type": "Circle3d -> Float"
            },
            {
                "name": "diameter",
                "comment": " Get the diameter of a circle.\n\n    Circl3d.diameter exampleCircle\n    --> 6\n\n",
                "type": "Circle3d -> Float"
            },
            {
                "name": "mirrorAcross",
                "comment": " Mirror a circle across a given plane.\n\n    Circle3d.mirrorAcross Plane3d.xy exampleCircle\n    --> Circle3d.with\n    -->     { centerPoint =\n    -->         Point3d.fromCoordinates ( 2, 0, -1 )\n    -->     , axialDirection = Direction3d.negativeZ\n    -->     , radius = 3\n    -->     }\n\n",
                "type": "Plane3d -> Circle3d -> Circle3d"
            },
            {
                "name": "on",
                "comment": " Construct a 3D circle lying _on_ a sketch plane by providing a 2D circle\nspecified in XY coordinates _within_ the sketch plane.\n\n    Circle3d.on SketchPlane3d.yz <|\n        Circle2d.with\n            { centerPoint =\n                Point2d.fromCoordinates ( 1, 2 )\n            , radius = 3\n            }\n    --> Circle3d.with\n    -->     { centerPoint =\n    -->         Point3d.fromCoordinates ( 0, 1, 2 )\n    -->     , axialDirection = Direction3d.x\n    -->     , radius = 3\n    -->     }\n\n",
                "type": "SketchPlane3d -> Circle2d -> Circle3d"
            },
            {
                "name": "placeIn",
                "comment": " Take a circle considered to be defined in local coordinates relative to a\ngiven reference frame, and return that circle expressed in global coordinates.\n\n    localFrame =\n        Frame3d.atPoint\n            (Point3d.fromCoordinates ( 1, 2, 3 ))\n\n    Circle3d.placeIn localFrame exampleCircle\n    --> Circle3d.with\n    -->     { centerPoint =\n    -->         Point3d.fromCoordinates ( 3, 2, 4 )\n    -->     , axialDirection = Direction3d.z\n    -->     , radius = 3\n    -->     }\n\n",
                "type": "Frame3d -> Circle3d -> Circle3d"
            },
            {
                "name": "plane",
                "comment": " Get the plane that a circle lies in. The origin point of the returned plane\nwill be the center point of the circle, and its normal direction will be the\naxial direction of the circle.\n\n    Circle3d.plane exampleCircle\n    --> Plane3d.with\n    -->     { originPoint =\n    -->         Point3d.fromCoordinates ( 2, 0, 1 )\n    -->     , normalDirection = Direction3d.z\n    -->     }\n\n",
                "type": "Circle3d -> Plane3d"
            },
            {
                "name": "projectInto",
                "comment": " Project a circle into a sketch plane.\n\n    inclinedCircle : Circle3d\n    inclinedCircle =\n        Circle3d.with\n            { centerPoint =\n                Point3d.fromCoordinates ( 1, 2, 3 )\n            , radius = 1\n            , axialDirection =\n                Direction3d.with\n                    { azimuth = 0\n                    , elevation = degrees 45\n                    }\n            }\n\n    Circle3d.projectInto SketchPlane3d.xy inclinedCircle\n    --> Ellipse2d.with\n    -->     { centerPoint =\n    -->         Point2d.fromCoordinates ( 1, 2 )\n    -->     , xDirection = Direction2d.negativeY\n    -->     , xRadius = 1\n    -->     , yRadius = 0.7071\n    -->     }\n\n",
                "type": "SketchPlane3d -> Circle3d -> Ellipse2d"
            },
            {
                "name": "radius",
                "comment": " Get the radius of a circle.\n\n    Circle3d.radius exampleCircle\n    --> 3\n\n",
                "type": "Circle3d -> Float"
            },
            {
                "name": "relativeTo",
                "comment": " Take a circle defined in global coordinates, and return it expressed in\nlocal coordinates relative to a given reference frame.\n\n    localFrame =\n        Frame3d.atPoint\n            (Point3d.fromCoordinates ( 1, 2, 3 ))\n\n    Circle3d.relativeTo localFrame exampleCircle\n    --> Circle3d.with\n    -->     { centerPoint =\n    -->         Point3d.fromCoordinates ( 1, -2, -2 )\n    -->     , axialDirection = Direction3d.z\n    -->     , radius = 3\n    -->     }\n\n",
                "type": "Frame3d -> Circle3d -> Circle3d"
            },
            {
                "name": "rotateAround",
                "comment": " Rotate a circle around a given axis by a given angle (in radians).\n\n    exampleCircle\n        |> Circle3d.rotateAround Axis3d.y (degrees 90)\n    --> Circle3d.with\n    -->     { centerPoint =\n    -->         Point3d.fromCoordinates ( 1, 0, -2 )\n    -->     , axialDirection = Direction3d.x\n    -->     , radius = 3\n    -->     }\n\n",
                "type": "Axis3d -> Float -> Circle3d -> Circle3d"
            },
            {
                "name": "scaleAbout",
                "comment": " Scale a circle around a given point by a given scale.\n\n    Circle3d.scaleAbout Point3d.origin 3 exampleCircle\n    --> Circle3d.with\n    -->     { centerPoint =\n    -->         Point3d.fromCoordinates ( 6, 0, 3 )\n    -->     , axialDirection = Direction3d.z\n    -->     , radius = 9\n    -->     }\n\n",
                "type": "Point3d -> Float -> Circle3d -> Circle3d"
            },
            {
                "name": "throughPoints",
                "comment": " Attempt to construct a circle that passes through the three given points.\nThe axial direction of the returned circle will be such that the three points\nare in counterclockwise order around it, according to the right-hand rule. If\nthe three given points are collinear, returns `Nothing`.\n\n    Circle3d.throughPoints\n        ( Point3d.fromCoordinates ( 1, 0, 0 )\n        , Point3d.fromCoordinates ( 0, 1, 0 )\n        , Point3d.fromCoordinates ( 0, 0, 1 )\n        )\n    --> Just\n    -->     (Circle3d.with\n    -->         { centerPoint =\n    -->             Point3d.fromCoordinates\n    -->                 ( 0.333, 0.333, 0.333 )\n    -->         , axialDirection =\n    -->             Direction3d.with\n    -->                 { azimuth = degrees 45\n    -->                 , elevation = degrees 35.26\n    -->                 }\n    -->         , radius = 0.8165\n    -->         }\n    -->     )\n\n",
                "type": "( Point3d, Point3d, Point3d ) -> Maybe Circle3d"
            },
            {
                "name": "translateBy",
                "comment": " Translate a circle by a given displacement.\n\n    displacement =\n        Vector3d.fromComponents ( 2, 1, 3 )\n\n    Circle3d.translateBy displacement exampleCircle\n    --> Circle3d.with\n    -->     { centerPoint =\n    -->         Point3d.fromCoordinates ( 4, 1, 4 )\n    -->     , axialDirection = Direction3d.z\n    -->     , radius = 3\n    -->     }\n\n",
                "type": "Vector3d -> Circle3d -> Circle3d"
            },
            {
                "name": "with",
                "comment": " Construct a circle from its center point, axial direction and radius:\n\n    exampleCircle =\n        Circle3d.with\n            { centerPoint =\n                Point3d.fromCoordinates ( 2, 0, 1 )\n            , axialDirection = Direction3d.z\n            , radius = 3\n            }\n\nThe actual radius of the circle will be the absolute value of the given radius\n(passing `radius = -2` will have the same effect as `radius = 2`).\n\n",
                "type": "{ centerPoint : Point3d, axialDirection : Direction3d, radius : Float } -> Circle3d"
            }
        ],
        "binops": []
    },
    {
        "name": "OpenSolid.QuadraticSpline3d",
        "comment": " <img src=\"https://opensolid.github.io/images/geometry/icons/quadraticSpline3d.svg\" alt=\"QuadraticSpline3d\" width=\"160\">\n\nA `QuadraticSpline3d` is a quadratic [Bézier curve](https://en.wikipedia.org/wiki/B%C3%A9zier_curve)\nin 3D defined by three control points. This module contains functionality for\n\n  - Evaluating points and derivatives along a spline\n  - Scaling, rotating, translating or mirroring a spline\n  - Converting a spline between local and global coordinates in different\n    reference frames\n\n@docs QuadraticSpline3d\n\n\n# Constructors\n\n@docs fromControlPoints, on\n\n\n# Properties\n\n@docs controlPoints, startPoint, endPoint, startDerivative, endDerivative\n\n\n# Evaluation\n\n@docs pointOn, derivative, evaluate\n\n\n# Transformations\n\n@docs reverse, scaleAbout, rotateAround, translateBy, mirrorAcross, projectOnto\n\n\n# Coordinate conversions\n\n@docs relativeTo, placeIn\n\n\n# Sketch planes\n\n@docs projectInto\n\n\n# Subdivision\n\n@docs bisect, splitAt\n\n\n# Arc length parameterization\n\n@docs ArcLengthParameterized, arcLengthParameterized, arcLength, pointAlong, tangentAlong, arcLengthToParameterValue, parameterValueToArcLength\n\n\n# Low level\n\nLow level functionality that you are unlikely to need to use directly.\n\n@docs derivativeMagnitude, secondDerivative\n\n",
        "unions": [
            {
                "name": "ArcLengthParameterized",
                "comment": " A spline that has been parameterized by arc length.\n",
                "args": [],
                "cases": []
            }
        ],
        "aliases": [
            {
                "name": "QuadraticSpline3d",
                "comment": " ",
                "args": [],
                "type": "QuadraticSpline3d"
            }
        ],
        "values": [
            {
                "name": "arcLength",
                "comment": " Find the total arc length of a spline. This will be accurate to within the\ntolerance given when calling `arcLengthParameterized`.\n\n    arcLength : Float\n    arcLength =\n        QuadraticSpline3d.arcLength parameterizedSpline\n\n    arcLength\n    --> 3.8175\n\n",
                "type": "ArcLengthParameterized -> Float"
            },
            {
                "name": "arcLengthParameterized",
                "comment": " Build an arc length parameterization of the given spline, within\na given tolerance. Generally speaking, all operations on the resulting\n`ArcLengthParameterized` value will be accurate to within the given arc length\ntolerance.\n\n    tolerance =\n        1.0e-4\n\n    parameterizedSpline =\n        QuadraticSpline3d.arcLengthParameterized\n            tolerance\n            exampleSpline\n\n",
                "type": "Float -> QuadraticSpline3d -> ArcLengthParameterized"
            },
            {
                "name": "arcLengthToParameterValue",
                "comment": " Try to get the parameter value along a spline at a given arc length. If the\ngiven arc length is less than zero or greater than the arc length of the spline,\nreturns `Nothing`.\n\n    QuadraticSpline3d.arcLengthToParameterValue\n        parameterizedSpline\n        (arcLength / 4)\n    --> Just 0.2328\n\n",
                "type": "ArcLengthParameterized -> Float -> Maybe Float"
            },
            {
                "name": "bisect",
                "comment": " Split a spline into two roughly equal halves. Equivalent to `splitAt 0.5`.\n\n    QuadraticSpline3d.bisect exampleSpline\n    --> ( QuadraticSpline3d.fromControlPoints\n    -->     ( Point3d.fromCoordinates ( 1, 1, 1 )\n    -->     , Point3d.fromCoordinates ( 2, 2.5 )\n    -->     , Point3d.fromCoordinates ( 3, 2.5 )\n    -->     )\n    --> , QuadraticSpline3d.fromControlPoints\n    -->     ( Point3d.fromCoordinates ( 3, 2.5 )\n    -->     , Point3d.fromCoordinates ( 4, 2.5 )\n    -->     , Point3d.fromCoordinates ( 3, 3, 3 )\n    -->     )\n    --> )\n\n",
                "type": "QuadraticSpline3d -> ( QuadraticSpline3d, QuadraticSpline3d )"
            },
            {
                "name": "controlPoints",
                "comment": " Get the control points of a spline as a tuple.\n\n    ( p1, p2, p3 ) =\n        QuadraticSpline3d.controlPoints exampleSpline\n\n\n    --> p1 = Point3d.fromCoordinates ( 1, 1, 1 )\n    --> p2 = Point3d.fromCoordinates ( 3, 2, 1 )\n    --> p3 = Point3d.fromCoordinates ( 3, 3, 3 )\n\n",
                "type": "QuadraticSpline3d -> ( Point3d, Point3d, Point3d )"
            },
            {
                "name": "derivative",
                "comment": " Get the deriative value at a point along a spline, based on a parameter that\nranges from 0 to 1. A parameter value of 0 corresponds to the start derivative\nof the spline and a value of 1 corresponds to the end derivative.\n\n    QuadraticSpline3d.derivative exampleSpline 0\n    --> Vector3d.fromComponents ( 4, 2, 0 )\n\n    QuadraticSpline3d.derivative exampleSpline 0.5\n    --> Vector3d.fromComponents ( 2, 2, 2 )\n\n    QuadraticSpline3d.derivative exampleSpline 1\n    --> Vector3d.fromComponents ( 0, 2, 4 )\n\nNote that the derivative interpolates linearly from end to end.\n\n",
                "type": "QuadraticSpline3d -> Float -> Vector3d"
            },
            {
                "name": "derivativeMagnitude",
                "comment": " Find the magnitude of the derivative to a spline at a particular parameter\nvalue;\n\n    QuadraticSpline3d.derivativeMagnitude spline t\n\nis equivalent to\n\n    Vector3d.length (QuadraticSpline3d.derivative spline t)\n\nbut more efficient since it avoids any intermediate `Vector3d` allocation.\n\n",
                "type": "QuadraticSpline3d -> Float -> Float"
            },
            {
                "name": "endDerivative",
                "comment": " Get the end derivative of a spline. This is equal to twice the vector from\nthe spline's second control point to its third.\n\n    QuadraticSpline3d.endDerivative exampleSpline\n    --> Vector3d.fromComponents ( 0, 2, 4 )\n\n",
                "type": "QuadraticSpline3d -> Vector3d"
            },
            {
                "name": "endPoint",
                "comment": " Get the end point of a spline. This is equal to the spline's last control\npoint.\n\n    QuadraticSpline3d.endPoint exampleSpline\n    --> Point3d.fromCoordinates ( 3, 3, 3 )\n\n",
                "type": "QuadraticSpline3d -> Point3d"
            },
            {
                "name": "evaluate",
                "comment": " Evaluate a spline at a given parameter value, returning the point on the\nspline at that parameter value and the derivative with respect to that parameter\nvalue;\n\n    QuadraticSpline3d.evaluate spline t\n\nis equivalent to\n\n    ( QuadraticSpline3d.pointOn spline t\n    , QuadraticSpline3d.derivative spline t\n    )\n\nbut is more efficient.\n\n",
                "type": "QuadraticSpline3d -> Float -> ( Point3d, Vector3d )"
            },
            {
                "name": "fromControlPoints",
                "comment": " Construct a spline from its three control points:\n\n    exampleSpline =\n        QuadraticSpline3d.fromControlPoints\n            ( Point3d.fromCoordinates ( 1, 1, 1 )\n            , Point3d.fromCoordinates ( 3, 2, 1 )\n            , Point3d.fromCoordinates ( 3, 3, 3 )\n            )\n\n",
                "type": "( Point3d, Point3d, Point3d ) -> QuadraticSpline3d"
            },
            {
                "name": "mirrorAcross",
                "comment": " Mirror a spline across a plane.\n\n    QuadraticSpline3d.mirrorAcross Plane3d.xy exampleSpline\n    --> QuadraticSpline3d.fromControlPoints\n    -->     ( Point3d.fromCoordinates ( 1, 1, -1 )\n    -->     , Point3d.fromCoordinates ( 3, 2, -1 )\n    -->     , Point3d.fromCoordinates ( 3, 3, -3 )\n    -->     )\n\n",
                "type": "Plane3d -> QuadraticSpline3d -> QuadraticSpline3d"
            },
            {
                "name": "on",
                "comment": " Construct a 3D spline lying _on_ a sketch plane by providing a 2D spline\nspecified in XY coordinates _within_ the sketch plane.\n\n    QuadraticSpline3d.on SketchPlane3d.xz <|\n        QuadraticSpline2d.fromControlPoints\n            ( Point2d.fromCoordinates ( 1, 1 )\n            , Point2d.fromCoordinates ( 3, 4 )\n            , Point2d.fromCoordinates ( 5, 1 )\n            )\n    --> QuadraticSpline3d.fromControlPoints\n    -->     ( Point3d.fromCoordinates ( 1, 0, 1 )\n    -->     , Point3d.fromCoordinates ( 3, 0, 4 )\n    -->     , Point3d.fromCoordinates ( 5, 0, 1 )\n    -->     )\n\n",
                "type": "SketchPlane3d -> QuadraticSpline2d -> QuadraticSpline3d"
            },
            {
                "name": "parameterValueToArcLength",
                "comment": " Try to get the arc length along a spline at a given parameter value. If the\ngiven parameter value is less than zero or greater than one, returns `Nothing`.\n\n    QuadraticSpline3d.parameterValueToArcLength\n        parameterizedSpline\n        0.25\n    --> Just 1.0192\n\n",
                "type": "ArcLengthParameterized -> Float -> Maybe Float"
            },
            {
                "name": "placeIn",
                "comment": " Take a spline considered to be defined in local coordinates relative to a\ngiven reference frame, and return that spline expressed in global coordinates.\n\n    localFrame =\n        Frame3d.atPoint\n            (Point3d.fromCoordinates ( 1, 2, 3 ))\n\n    QuadraticSpline3d.placeIn localFrame exampleSpline\n    --> QuadraticSpline3d.fromControlPoints\n    -->     ( Point3d.fromCoordinates ( 2, 3, 4 )\n    -->     , Point3d.fromCoordinates ( 4, 4, 4 )\n    -->     , Point3d.fromCoordinates ( 4, 5, 6 )\n    -->     )\n\n",
                "type": "Frame3d -> QuadraticSpline3d -> QuadraticSpline3d"
            },
            {
                "name": "pointAlong",
                "comment": " Try to get the point along a spline at a given arc length. For example, to\nget the point a quarter of the way along `exampleSpline`:\n\n    QuadraticSpline3d.pointAlong parameterizedSpline\n        (arcLength / 4)\n    --> Just <|\n    -->     Point3d.fromCoordinates\n    -->         ( 1.8227, 1.4655, 1.1083 )\n\nNote that this is not the same as evaulating at a parameter value of 1/4:\n\n    QuadraticSpline3d.pointOn exampleSpline 0.25\n    --> Point3d.fromCoordinates ( 1.875, 1.5, 1.125 )\n\nIf the given arc length is less than zero or greater than the arc length of the\nspline, `Nothing` is returned.\n\n",
                "type": "ArcLengthParameterized -> Float -> Maybe Point3d"
            },
            {
                "name": "pointOn",
                "comment": " Get a point along a spline, based on a parameter that ranges from 0 to 1. A\nparameter value of 0 corresponds to the start point of the spline and a value of\n1 corresponds to the end point.\n\n    QuadraticSpline3d.pointOn exampleSpline 0\n    --> Point3d.fromCoordinates ( 1, 1, 1 )\n\n    QuadraticSpline3d.pointOn exampleSpline 0.5\n    --> Point3d.fromCoordinates ( 2.5, 2, 1.5 )\n\n    QuadraticSpline3d.pointOn exampleSpline 1\n    --> Point3d.fromCoordinates ( 3, 3, 3 )\n\n",
                "type": "QuadraticSpline3d -> Float -> Point3d"
            },
            {
                "name": "projectInto",
                "comment": " Project a spline into a given sketch plane. Conceptually, finds the\n[orthographic projection](https://en.wikipedia.org/wiki/Orthographic_projection)\nof the spline onto the plane and then expresses the projected spline in 2D\nsketch coordinates.\n\n    exampleSpline\n        |> QuadraticSpline3d.projectInto SketchPlane3d.yz\n    --> QuadraticSpline2d.fromControlPoints\n    -->     ( Point2d.fromCoordinates ( 1, 1 )\n    -->     , Point2d.fromCoordinates ( 2, 1 )\n    -->     , Point2d.fromCoordinates ( 3, 3 )\n    -->     )\n\n",
                "type": "SketchPlane3d -> QuadraticSpline3d -> QuadraticSpline2d"
            },
            {
                "name": "projectOnto",
                "comment": " Find the [orthographic projection](https://en.wikipedia.org/wiki/Orthographic_projection)\nof a spline onto a plane.\n\n    QuadraticSpline3d.projectOnto Plane3d.xy exampleSpline\n    --> QuadraticSpline3d.fromControlPoints\n    -->     ( Point3d.fromCoordinates ( 1, 1, 0 )\n    -->     , Point3d.fromCoordinates ( 3, 2, 0 )\n    -->     , Point3d.fromCoordinates ( 3, 3, 0 )\n    -->     )\n\n",
                "type": "Plane3d -> QuadraticSpline3d -> QuadraticSpline3d"
            },
            {
                "name": "relativeTo",
                "comment": " Take a spline defined in global coordinates, and return it expressed in\nlocal coordinates relative to a given reference frame.\n\n    localFrame =\n        Frame3d.atPoint\n            (Point3d.fromCoordinates ( 1, 2, 3 ))\n\n    QuadraticSpline3d.relativeTo localFrame exampleSpline\n    --> QuadraticSpline3d.fromControlPoints\n    -->     ( Point3d.fromCoordinates ( 0, -1, -2 )\n    -->     , Point3d.fromCoordinates ( 2, 0, -2 )\n    -->     , Point3d.fromCoordinates ( 2, 1, 0 )\n    -->     )\n\n",
                "type": "Frame3d -> QuadraticSpline3d -> QuadraticSpline3d"
            },
            {
                "name": "reverse",
                "comment": " Reverse a spline so that the start point becomes the end point, and vice\nversa.\n\n    QuadraticSpline3d.reverse exampleSpline\n    --> QuadraticSpline3d.fromControlPoints\n    -->     ( Point3d.fromCoordinates ( 3, 3, 3 )\n    -->     , Point3d.fromCoordinates ( 3, 2, 1 )\n    -->     , Point3d.fromCoordinates ( 1, 1, 1 )\n    -->     )\n\n",
                "type": "QuadraticSpline3d -> QuadraticSpline3d"
            },
            {
                "name": "rotateAround",
                "comment": " Rotate a spline counterclockwise around a given axis by a given angle (in\nradians).\n\n    exampleSpline\n        |> QuadraticSpline3d.rotateAround Axis3d.z\n            (degrees 90)\n    --> QuadraticSpline3d.fromControlPoints\n    -->     ( Point3d.fromCoordinates ( -1, 1, 1 )\n    -->     , Point3d.fromCoordinates ( -2, 3, 1 )\n    -->     , Point3d.fromCoordinates ( -3, 3, 3 )\n    -->     )\n\n",
                "type": "Axis3d -> Float -> QuadraticSpline3d -> QuadraticSpline3d"
            },
            {
                "name": "scaleAbout",
                "comment": " Scale a spline about the given center point by the given scale.\n\n    exampleSpline\n        |> QuadraticSpline3d.scaleAbout Point3d.origin 2\n    --> QuadraticSpline3d.fromControlPoints\n    -->     ( Point3d.fromCoordinates ( 2, 2, 2 )\n    -->     , Point3d.fromCoordinates ( 6, 4, 2 )\n    -->     , Point3d.fromCoordinates ( 6, 6, 6 )\n    -->     )\n\n",
                "type": "Point3d -> Float -> QuadraticSpline3d -> QuadraticSpline3d"
            },
            {
                "name": "secondDerivative",
                "comment": " Get the second derivative of a spline (for a quadratic spline, this is a\nconstant).\n",
                "type": "QuadraticSpline3d -> Vector3d"
            },
            {
                "name": "splitAt",
                "comment": " Split a spline at a particular parameter value (in the range 0 to 1),\nresulting in two smaller splines.\n\n    QuadraticSpline3d.splitAt 0.75 exampleSpline\n    --> ( QuadraticSpline3d.fromControlPoints\n    -->     ( Point3d.fromCoordinates ( 1, 1, 1 )\n    -->     , Point3d.fromCoordinates ( 2, 1.5, 1 )\n    -->     , Point3d.fromCoordinates ( 2.5, 2, 1.5 )\n    -->     )\n    --> , QuadraticSpline3d.fromControlPoints\n    -->     ( Point3d.fromCoordinates ( 2.5, 2, 1.5 )\n    -->     , Point3d.fromCoordinates ( 3, 2.5, 2 )\n    -->     , Point3d.fromCoordinates ( 3, 3, 3 )\n    -->     )\n    --> )\n\n",
                "type": "Float -> QuadraticSpline3d -> ( QuadraticSpline3d, QuadraticSpline3d )"
            },
            {
                "name": "startDerivative",
                "comment": " Get the start derivative of a spline. This is equal to twice the vector from\nthe spline's first control point to its second.\n\n    QuadraticSpline3d.startDerivative exampleSpline\n    --> Vector3d.fromComponents ( 4, 2, 0 )\n\n",
                "type": "QuadraticSpline3d -> Vector3d"
            },
            {
                "name": "startPoint",
                "comment": " Get the start point of a spline. This is equal to the spline's first control\npoint.\n\n    QuadraticSpline3d.startPoint exampleSpline\n    --> Point3d.fromCoordinates ( 1, 1, 1 )\n\n",
                "type": "QuadraticSpline3d -> Point3d"
            },
            {
                "name": "tangentAlong",
                "comment": " Try to get the tangent direction along a spline at a given arc length. To\nget the tangent direction a quarter of the way along `exampleSpline`:\n\n    QuadraticSpline3d.tangentAlong parameterizedSpline\n        (arcLength / 4)\n    --> Just <|\n    -->     Direction3d.with\n    -->         { azimuth = degrees 33.091\n    -->         , elevation = degrees 14.260\n    -->         }\n\nIf the given arc length is less than zero or greater than the arc length of the\nspline (or if the derivative of the spline happens to be exactly zero at the\ngiven arc length), `Nothing` is returned.\n\n",
                "type": "ArcLengthParameterized -> Float -> Maybe Direction3d"
            },
            {
                "name": "translateBy",
                "comment": " Translate a spline by a given displacement.\n\n    displacement =\n        Vector3d.fromComponents ( 2, 3, 1 )\n\n    exampleSpline\n        |> QuadraticSpline3d.translateBy displacement\n    --> QuadraticSpline3d.fromControlPoints\n    -->     ( Point3d.fromCoordinates ( 3, 4, 2 )\n    -->     , Point3d.fromCoordinates ( 5, 5, 2 )\n    -->     , Point3d.fromCoordinates ( 5, 6, 4 )\n    -->     )\n\n",
                "type": "Vector3d -> QuadraticSpline3d -> QuadraticSpline3d"
            }
        ],
        "binops": []
    },
    {
        "name": "OpenSolid.Frame3d",
        "comment": " <img src=\"https://opensolid.github.io/images/geometry/icons/frame3d.svg\" alt=\"Frame3d\" width=\"160\">\n\nA `Frame3d` has an origin point and a set of X, Y and Z directions (which are\nalways perpendicular to each other). It can be thought of as:\n\n  - A local coordinate system: Most geometric types have associated `relativeTo`\n    and `placeIn` functions that convert values of that type from global\n    coordinates to local coordinates in a particular frame, and vice versa.\n  - A set of axes and planes: It is often convenient to (for example) rotate\n    around the Z axis of a frame, or mirror across its XY plane. Frames can\n    also themselves be translated, rotated and mirrored!\n  - A combined 3D position and orientation: For example, a `Frame3d` could be\n    used to define the position and orientation of a spaceship in a 3D game.\n    Movement of the ship would then be done by translating and rotating the\n    frame.\n\n@docs Frame3d\n\n\n# Constants\n\n@docs xyz\n\n\n# Constructors\n\n@docs atPoint, with, unsafe\n\n\n# Properties\n\n@docs originPoint, xDirection, yDirection, zDirection, isRightHanded\n\n\n## Axes\n\n@docs xAxis, yAxis, zAxis\n\n\n## Planes\n\nThe following functions all return planes with the same origin point as the\ngiven plane, but with varying normal directions. In each case the normal\ndirection of the resulting plane is given by the cross product of the two\nindicated basis directions (assuming a right-handed frame); for example,\n\n    Frame3d.xyPlane Frame3d.xyz\n    --> Plane3d.with\n    -->     { originPoint = Point3d.origin\n    -->     , normalDirection = Direction3d.positiveZ\n    -->     }\n\nsince the cross product of the X and Y basis directions of a frame is equal to\nits Z basis direction. And since reversing the order of arguments in a cross\nproduct reverses the sign of the result,\n\n    Frame3d.yxPlane Frame3d.xyz\n    --> Plane3d.with\n    -->     { originPoint = Point3d.origin\n    -->     , normalDirection = Direction3d.negativeZ\n    -->     }\n\n@docs xyPlane, yxPlane, yzPlane, zyPlane, zxPlane, xzPlane\n\n\n## Sketch planes\n\nThese functions all form a `SketchPlane3d` from two axes of the given frame. The\nX and Y axes of the sketch plane will correspond to the two indicated axes. For\nexample,\n\n    yzSketchPlane =\n        Frame3d.yzSketchPlane Frame3d.xyz\n\n    SketchPlane3d.originPoint yzSketchPlane\n    --> Point3d.origin\n\n    SketchPlane3d.xDirection yzSketchPlane\n    --> Direction3d.y\n\n    SketchPlane3d.yDirection yzSketchPlane\n    --> Direction3d.z\n\nNote that this can be confusing - for example, a local X coordinate in the above\nsketch plane corresponds to a global Y coordinate, and a local Y coordinate\ncorresponds to a global Z coordinate!\n\n@docs xySketchPlane, yxSketchPlane, yzSketchPlane, zySketchPlane, zxSketchPlane, xzSketchPlane\n\n\n# Transformations\n\n@docs flipX, flipY, flipZ, moveTo, rotateAround, rotateAroundOwn, translateBy, translateAlongOwn, mirrorAcross\n\n\n# Coordinate conversions\n\n@docs relativeTo, placeIn\n\n",
        "unions": [],
        "aliases": [
            {
                "name": "Frame3d",
                "comment": " ",
                "args": [],
                "type": "Frame3d"
            }
        ],
        "values": [
            {
                "name": "atPoint",
                "comment": " Construct a frame aligned with the global XYZ frame but with the given\norigin point.\n\n    frame =\n        Frame3d.atPoint\n            (Point3d.fromCoordinates ( 2, 1, 3 ))\n\n    Frame3d.originPoint frame\n    --> Point3d.fromCoordinates ( 2, 1, 3 )\n\n    Frame3d.xDirection frame\n    --> Direction3d.x\n\n    Frame3d.yDirection frame\n    --> Direction3d.y\n\n    Frame3d.zDirection frame\n    --> Direction3d.z\n\n",
                "type": "Point3d -> Frame3d"
            },
            {
                "name": "flipX",
                "comment": " Reverse the X direction of a frame.\n\n    Frame3d.xDirection (Frame3d.flipX Frame3d.xyz)\n    --> Direction3d.negativeX\n\nNote that this will switch the [handedness](https://en.wikipedia.org/wiki/Cartesian_coordinate_system#Orientation_and_handedness)\nof the frame.\n\n",
                "type": "Frame3d -> Frame3d"
            },
            {
                "name": "flipY",
                "comment": " Reverse the Y direction of a frame.\n\n    Frame3d.yDirection (Frame3d.flipY Frame3d.xyz)\n    --> Direction3d.negativeY\n\nNote that this will switch the [handedness](https://en.wikipedia.org/wiki/Cartesian_coordinate_system#Orientation_and_handedness)\nof the frame.\n\n",
                "type": "Frame3d -> Frame3d"
            },
            {
                "name": "flipZ",
                "comment": " Reverse the Z direction of a frame.\n\n    Frame3d.zDirection (Frame3d.flipZ Frame3d.xyz)\n    --> Direction3d.negativeZ\n\nNote that this will switch the [handedness](https://en.wikipedia.org/wiki/Cartesian_coordinate_system#Orientation_and_handedness)\nof the frame.\n\n",
                "type": "Frame3d -> Frame3d"
            },
            {
                "name": "isRightHanded",
                "comment": " Check if a frame is [right-handed](https://en.wikipedia.org/wiki/Cartesian_coordinate_system#Orientation_and_handedness).\n\n    Frame3d.isRightHanded Frame3d.xyz\n    --> True\n\n    Frame3d.isRightHanded (Frame3d.flipZ Frame3d.xyz)\n    --> False\n\nAll predefined frames are right-handed, and most operations on frames preserve\nhandedness, so about the only ways to end up with a left-handed frame are by\nconstructing one explicitly with `unsafe` or by mirroring a right-handed frame.\n\n",
                "type": "Frame3d -> Bool"
            },
            {
                "name": "mirrorAcross",
                "comment": " Mirror a frame across a plane.\n\n    frame =\n        Frame3d.atPoint\n            (Point3d.fromCoordinates ( 2, 1, 3 ))\n\n    mirroredFrame =\n        Frame3d.mirrorAcross Plane3d.xy frame\n\n    Frame3d.originPoint mirroredFrame\n    --> Point3d.fromCoordinates ( 2, 1, -3 )\n\n    Frame3d.xDirection mirroredFrame\n    --> Direction3d.x\n\n    Frame3d.yDirection mirroredFrame\n    --> Direction3d.y\n\n    Frame3d.zDirection mirroredFrame\n    --> Direction3d.negativeZ\n\nNote that this will switch the [handedness](https://en.wikipedia.org/wiki/Cartesian_coordinate_system#Orientation_and_handedness)\nof the frame.\n\n",
                "type": "Plane3d -> Frame3d -> Frame3d"
            },
            {
                "name": "moveTo",
                "comment": " Move a frame so that it has the given origin point but unchanged\norientation.\n\n    point =\n        Point3d.fromCoordinates ( 2, 1, 3 )\n\n    Frame3d.moveTo point Frame3d.xyz\n    --> Frame3d.atPoint point\n\n",
                "type": "Point3d -> Frame3d -> Frame3d"
            },
            {
                "name": "originPoint",
                "comment": " Get the origin point of a given frame.\n\n    Frame3d.originPoint Frame3d.xyz\n    --> Point3d.origin\n\n",
                "type": "Frame3d -> Point3d"
            },
            {
                "name": "placeIn",
                "comment": " Take one frame defined in global coordinates and a second frame defined\nin local coordinates relative to the first frame, and return the second frame\nexpressed in global coordinates.\n",
                "type": "Frame3d -> Frame3d -> Frame3d"
            },
            {
                "name": "relativeTo",
                "comment": " Take two frames defined in global coordinates, and return the second one\nexpressed in local coordinates relative to the first.\n",
                "type": "Frame3d -> Frame3d -> Frame3d"
            },
            {
                "name": "rotateAround",
                "comment": " Rotate a frame around an axis by a given angle (in radians). The frame's\norigin point and basis directions will all be rotated around the given axis.\n\n    frame =\n        Frame3d.atPoint\n            (Point3d.fromCoordinates ( 2, 1, 3 ))\n\n    rotatedFrame =\n        Frame3d.rotateAround Axis3d.z (degrees 90) frame\n\n    Frame3d.originPoint rotatedFrame\n    --> Point3d.fromCoordinates ( -1, 2, 3 )\n\n    Frame3d.xDirection rotatedFrame\n    --> Direction3d.y\n\n    Frame3d.yDirection rotatedFrame\n    --> Direction3d.negativeX\n\n    Frame3d.zDirection rotatedFrame\n    --> Direction3d.z\n\n",
                "type": "Axis3d -> Float -> Frame3d -> Frame3d"
            },
            {
                "name": "rotateAroundOwn",
                "comment": " Rotate a frame around one of its own axes by a given angle (in radians).\n\nThe first argument is a function that returns the axis to rotate around, given\nthe current frame. The majority of the time this will be either `Frame3d.xAxis`,\n`Frame3d.yAxis` or `Frame3d.zAxis`. Compare the following to the above example\nfor `rotateAround`:\n\n    frame =\n        Frame3d.atPoint\n            (Point3d.fromCoordinates ( 2, 1, 3 ))\n\n    rotatedFrame =\n        frame\n            |> Frame3d.rotateAroundOwn Frame3d.zAxis\n                (degrees 90)\n\n    Frame3d.originPoint rotatedFrame\n    --> Point3d.fromCoordinates ( 2, 1, 3 )\n\n    Frame3d.xDirection rotatedFrame\n    --> Direction3d.y\n\n    Frame3d.yDirection rotatedFrame\n    --> Direction3d.negativeX\n\n    Frame3d.zDirection rotatedFrame\n    --> Direction3d.z\n\nSince the rotation is done around the frame's own Z axis (which passes through\nthe frame's origin point), the origin point remains the same after rotation.\n\nIn this example the frame's Z axis has the same orientation as the global Z axis\nso the frame's basis directions are rotated the same way, but in more complex\nexamples involving rotated frames a rotation around (for example) the frame's\nown Z axis may be completely different from a rotation around the global Z axis.\n\n",
                "type": "(Frame3d -> Axis3d) -> Float -> Frame3d -> Frame3d"
            },
            {
                "name": "translateAlongOwn",
                "comment": " Translate a frame along one of its own axes by a given distance.\n\nThe first argument is a function that returns the axis to translate along, given\nthe current frame. The majority of the time this will be either `Frame3d.xAxis`,\n`Frame3d.yAxis` or `Frame3d.zAxis`.\n\nThis function is convenient when constructing frames via a series of\ntransformations. For example,\n\n    point =\n        Point3d.fromCoordinates ( 2, 0, 0 )\n\n    frame =\n        Frame3d.atPoint point\n            |> Frame3d.rotateAroundOwn Frame3d.zAxis\n                (degrees 45)\n            |> Frame3d.translateAlongOwn Frame3d.xAxis 2\n\nmeans \"construct a frame at the point (2, 0, 0), rotate it around its own Z axis\ncounterclockwise by 45 degrees, then translate it along its own (rotated) X axis\nby 2 units\", resulting in\n\n    Frame3d.originPoint frame\n    --> Point3d.fromCoordinates ( 3.4142, 1.4142, 0 )\n\n    Frame3d.xDirection frame\n    --> Direction3d.with\n    -->     { azimuth = degrees 45\n    -->     , elevation = 0\n    -->     }\n\n    Frame3d.yDirection frame\n    --> Direction3d.with\n    -->     { azimuth = degrees 135\n    -->     , elevation = 0\n    -->     }\n\n    Frame3d.zDirection frame\n    --> Direction3d.z\n\n",
                "type": "(Frame3d -> Axis3d) -> Float -> Frame3d -> Frame3d"
            },
            {
                "name": "translateBy",
                "comment": " Translate a frame by a given displacement.\n\n    frame =\n        Frame3d.atPoint\n            (Point3d.fromCoordinates ( 2, 1, 3 ))\n\n    displacement =\n        Vector3d.fromComponents ( 1, 1, 1 )\n\n    Frame3d.translateBy displacement frame\n    --> Frame3d.atPoint\n    -->     (Point3d.fromCoordinates ( 3, 2, 4 ))\n\n",
                "type": "Vector3d -> Frame3d -> Frame3d"
            },
            {
                "name": "unsafe",
                "comment": " Construct a frame directly from its origin point and X, Y and Z directions:\n\n    frame =\n        Frame3d.unsafe\n            { originPoint =\n                Point3d.fromCoordinates ( 2, 1, 3 )\n            , xDirection =\n                Direction3d.unsafe ( 0.8, 0.6, 0 )\n            , yDirection =\n                Direction3d.unsafe ( -0.6, 0.8, 0 )\n            , zDirection =\n                Direction3d.unsafe ( 0, 0, 1 )\n            }\n\nIn this case **you must be careful to ensure that the X, Y and Z directions are\nperpendicular**. (You will likely also want to make sure that they form a\n[right-handed](https://en.wikipedia.org/wiki/Cartesian_coordinate_system#Orientation_and_handedness)\ncoordinate system.) To construct sets of mutually perpendicular directions,\n[`Direction3d.orthonormalize`](OpenSolid-Direction3d#orthonormalize),\n[`Direction3d.orthogonalize`](OpenSolid-Direction3d#orthogonalize), or\n[`Direction3d.perpendicularBasis`](OpenSolid-Direction3d#perpendicularBasis) may\nbe useful.\n\n",
                "type": "{ originPoint : Point3d, xDirection : Direction3d, yDirection : Direction3d, zDirection : Direction3d } -> Frame3d"
            },
            {
                "name": "with",
                "comment": " Construct a frame with the given origin point and Z direction. X and Y\ndirections will be chosen arbitrarily such that the frame has the desired Z\ndirection. This can be useful when constructing 'scratch' frames where the\nspecific X/Y directions are unimportant.\n\n    frame =\n        Frame3d.with\n            { originPoint = Point3d.origin\n            , zDirection =\n                Direction3d.with\n                    { azimuth = 0\n                    , elevation = degrees 60\n                    }\n            }\n\n    Frame3d.originPoint sketchPlane\n    --> Point3d.origin\n\n    Frame3d.xDirection sketchPlane\n    --> Direction3d.with\n    -->     { azimuth = degrees 0\n    -->     , elevation = degrees -30\n    -->     }\n\n    Frame3d.yDirection sketchPlane\n    --> Direction3d.y\n\n    Frame3d.zDirection sketchPlane\n    --> Direction3d.with\n    -->     { azimuth = 0\n    -->     , elevation = degrees 60\n    -->     }\n\n",
                "type": "{ originPoint : Point3d, zDirection : Direction3d } -> Frame3d"
            },
            {
                "name": "xAxis",
                "comment": " Get the X axis of a given frame (the axis formed from the frame's origin\npoint and X direction).\n\n    Frame3d.xAxis Frame3d.xyz\n    --> Axis3d.x\n\n",
                "type": "Frame3d -> Axis3d"
            },
            {
                "name": "xDirection",
                "comment": " Get the X direction of a given frame.\n\n    Frame3d.xDirection Frame3d.xyz\n    --> Direction3d.x\n\n",
                "type": "Frame3d -> Direction3d"
            },
            {
                "name": "xyPlane",
                "comment": " Get a plane with normal direction equal to the frame's positive Z direction.\n",
                "type": "Frame3d -> Plane3d"
            },
            {
                "name": "xySketchPlane",
                "comment": " Form a sketch plane from the given frame's X and Y axes.\n",
                "type": "Frame3d -> SketchPlane3d"
            },
            {
                "name": "xyz",
                "comment": " The global XYZ frame.\n\n    Frame3d.originPoint Frame3d.xyz\n    --> Point3d.origin\n\n    Frame3d.xDirection Frame3d.xyz\n    --> Direction3d.x\n\n    Frame3d.yDirection Frame3d.xyz\n    --> Direction3d.y\n\n    Frame3d.zDirection Frame3d.xyz\n    --> Direction3d.z\n\n",
                "type": "Frame3d"
            },
            {
                "name": "xzPlane",
                "comment": " Get a plane with normal direction equal to the frame's negative Y direction.\n",
                "type": "Frame3d -> Plane3d"
            },
            {
                "name": "xzSketchPlane",
                "comment": " Form a sketch plane from the given frame's X and Z axes.\n",
                "type": "Frame3d -> SketchPlane3d"
            },
            {
                "name": "yAxis",
                "comment": " Get the Y axis of a given frame (the axis formed from the frame's origin\npoint and Y direction).\n\n    Frame3d.yAxis Frame3d.xyz\n    --> Axis3d.y\n\n",
                "type": "Frame3d -> Axis3d"
            },
            {
                "name": "yDirection",
                "comment": " Get the Y direction of a given frame.\n\n    Frame3d.yDirection Frame3d.xyz\n    --> Direction3d.y\n\n",
                "type": "Frame3d -> Direction3d"
            },
            {
                "name": "yxPlane",
                "comment": " Get a plane with normal direction equal to the frame's negative Z direction.\n",
                "type": "Frame3d -> Plane3d"
            },
            {
                "name": "yxSketchPlane",
                "comment": " Form a sketch plane from the given frame's Y and X axes.\n",
                "type": "Frame3d -> SketchPlane3d"
            },
            {
                "name": "yzPlane",
                "comment": " Get a plane with normal direction equal to the frame's positive X direction.\n",
                "type": "Frame3d -> Plane3d"
            },
            {
                "name": "yzSketchPlane",
                "comment": " Form a sketch plane from the given frame's Y and Z axes.\n",
                "type": "Frame3d -> SketchPlane3d"
            },
            {
                "name": "zAxis",
                "comment": " Get the Z axis of a given frame (the axis formed from the frame's origin\npoint and Z direction).\n\n    Frame3d.zAxis Frame3d.xyz\n    --> Axis3d.z\n\n",
                "type": "Frame3d -> Axis3d"
            },
            {
                "name": "zDirection",
                "comment": " Get the Z direction of a given frame.\n\n    Frame3d.zDirection Frame3d.xyz\n    --> Direction3d.z\n\n",
                "type": "Frame3d -> Direction3d"
            },
            {
                "name": "zxPlane",
                "comment": " Get a plane with normal direction equal to the frame's positive Y direction.\n",
                "type": "Frame3d -> Plane3d"
            },
            {
                "name": "zxSketchPlane",
                "comment": " Form a sketch plane from the given frame's Z and X axes.\n",
                "type": "Frame3d -> SketchPlane3d"
            },
            {
                "name": "zyPlane",
                "comment": " Get a plane with normal direction equal to the frame's negative X direction.\n",
                "type": "Frame3d -> Plane3d"
            },
            {
                "name": "zySketchPlane",
                "comment": " Form a sketch plane from the given frame's Z and Y axes.\n",
                "type": "Frame3d -> SketchPlane3d"
            }
        ],
        "binops": []
    },
    {
        "name": "OpenSolid.Arc2d",
        "comment": " <img src=\"https://opensolid.github.io/images/geometry/icons/arc2d.svg\" alt=\"Arc2d\" width=\"160\">\n\nAn `Arc2d` is a section of a circle, defined by its center point, start\npoint and swept angle (the counterclockwise angle from the start point to the\nend point). This module includes functionality for\n\n  - Constructing arcs through given points and/or with a given radius\n  - Scaling, rotating, translating and mirroring arcs\n  - Converting arcs between different coordinate systems\n\n@docs Arc2d\n\n\n# Constructors\n\n@docs with, throughPoints, fromEndpoints, SweptAngle, smallPositive, smallNegative, largePositive, largeNegative\n\n\n# Properties\n\n@docs centerPoint, radius, startPoint, endPoint, sweptAngle\n\n\n# Evaluation\n\n@docs pointOn, derivative, evaluate\n\n\n# Linear approximation\n\n@docs toPolyline\n\n\n# Transformations\n\n@docs reverse, scaleAbout, rotateAround, translateBy, mirrorAcross\n\n\n# Coordinate conversions\n\n@docs relativeTo, placeIn\n\n",
        "unions": [
            {
                "name": "SweptAngle",
                "comment": " Argument type used in [`fromEndpoints`](#fromEndpoints).\n",
                "args": [],
                "cases": []
            }
        ],
        "aliases": [
            {
                "name": "Arc2d",
                "comment": " ",
                "args": [],
                "type": "Arc2d"
            }
        ],
        "values": [
            {
                "name": "centerPoint",
                "comment": " Get the center point of an arc.\n\n    Arc2d.centerPoint exampleArc\n    --> Point2d.fromCoordinates ( 1, 1 )\n\n",
                "type": "Arc2d -> Point2d"
            },
            {
                "name": "derivative",
                "comment": " Get the derivative of an arc with respect to a parameter that is 0 at the\nstart point of the arc and 1 at the end point of the arc.\n\n    Arc2d.derivative exampleArc 0\n    --> Vector2d.fromComponents ( 0, 3.1416 )\n\n    Arc2d.derivative exampleArc 1\n    --> Vector2d.fromComponents ( -3.1416, 0 )\n\n",
                "type": "Arc2d -> Float -> Vector2d"
            },
            {
                "name": "endPoint",
                "comment": " Get the end point of an arc.\n\n    Arc2d.endPoint exampleArc\n    --> Point2d.fromCoordinates ( 1, 3 )\n\n",
                "type": "Arc2d -> Point2d"
            },
            {
                "name": "evaluate",
                "comment": " Evaluate an arc at a given parameter value, returning the point on the arc\nat that parameter value and the derivative with respect to that parameter value.\n\n    Arc2d.evaluate exampleArc 0\n    --> ( Point2d.fromCoordinates ( 3, 1 )\n    --> , Vector2d.fromComponents ( 0, 3.1416 )\n    --> )\n\n    Arc2d.evaluate exampleArc 0.5\n    --> ( Point2d.fromCoordinates ( 2.4142, 2.4142 )\n    --> , Vector2d.fromComponents ( -2.2214, 2.2214 )\n    --> )\n\n    Arc2d.evaluate exampleArc 1\n    --> ( Point2d.fromCoordinates ( 1, 3 )\n    --> , Vector2d.fromComponents ( -3.1416, 0 )\n    --> )\n\nEquivalent to (but more efficient than) calling `pointOn` and `derivative`\nseparately.\n\n",
                "type": "Arc2d -> Float -> ( Point2d, Vector2d )"
            },
            {
                "name": "fromEndpoints",
                "comment": " Attempt to construct an arc with the given start point, end point and\nradius. For any given valid set of start point, end point and radius, there are\nfour possible results, so the `sweptAngle` argument is used to specify which\narc to create:\n\n  - `Arc2d.smallPositive` will result in a counterclockwise arc with a small\n    swept angle (in the range 0..180 degrees)\n  - `Arc2d.smallNegative` will result in a clockwise arc with a small swept\n    angle (in the range -180..0 degrees)\n  - `Arc2d.largePositive` will result in a counterclockwise arc with a large\n    swept angle (in the range 180..360 degrees)\n  - `Arc2d.largeNegative` will result in a clockwise arc with a large swept\n    angle (in the range -360..-180 degrees)\n\nFor example:\n\n    p1 =\n        Point2d.fromCoordinates ( 1, 0 )\n\n    p2 =\n        Point2d.fromCoordinates ( 0, 1 )\n\n    Arc2d.fromEndpoints\n        { startPoint = p1\n        , endPoint = p2\n        , radius = 1\n        , sweptAngle = Arc2d.smallPositive\n        }\n    --> Just\n    -->     (Arc2d.with\n    -->         { startPoint =\n    -->             Point2d.fromCoordinates ( 1, 0 )\n    -->         , centerPoint = Point2d.origin\n    -->         , sweptAngle = degrees 90\n    -->         }\n    -->     )\n\n    Arc2d.fromEndpoints\n        { startPoint = p1\n        , endPoint = p2\n        , radius = 1\n        , sweptAngle = Arc2d.smallNegative\n        }\n    --> Just\n    -->     (Arc2d.with\n    -->         { startPoint =\n    -->             Point2d.fromCoordinates ( 1, 0 )\n    -->         , centerPoint =\n    -->             Point2d.fromCoordinates ( 1, 1 )\n    -->         , sweptAngle = degrees -90\n    -->         }\n    -->     )\n\n    Arc2d.fromEndpoints\n        { startPoint = p1\n        , endPoint = p2\n        , radius = 1\n        , sweptAngle = Arc2d.largePositive\n        }\n    --> Just\n    -->     (Arc2d.with\n    -->         { startPoint =\n    -->             Point2d.fromCoordinates ( 1, 0 )\n    -->         , centerPoint =\n    -->             Point2d.fromCoordinates ( 1, 1 )\n    -->         , sweptAngle = degrees 270\n    -->         }\n    -->     )\n\n    Arc2d.fromEndpoints\n        { startPoint = p1\n        , endPoint = p2\n        , radius = 1\n        , sweptAngle = Arc2d.largeNegative\n        }\n    --> Just\n    -->     (Arc2d.with\n    -->         { startPoint =\n    -->             Point2d.fromCoordinates ( 1, 0 )\n    -->         , centerPoint = Point2d.origin\n    -->         , sweptAngle = degrees -270\n    -->         }\n    -->     )\n\n    Arc2d.fromEndpoints\n        { startPoint = p1\n        , endPoint = p2\n        , radius = 2\n        , sweptAngle = Arc2d.smallPositive\n        }\n    --> Just\n    -->     (Arc2d.with\n    -->         { startPoint =\n    -->             Point2d.fromCoordinates ( 1, 0 )\n    -->         , centerPoint =\n    -->             Point2d.fromCoordinates\n    -->                 ( -0.8229\n    -->                 , -0.8229\n    -->                 )\n    -->         , sweptAngle = degrees 41.4096\n    -->         }\n    -->     )\n\nIf the start and end points are coincident or the distance between them is more\nthan twice the given radius, returns `Nothing`:\n\n    Arc2d.fromEndpoints\n        { startPoint = p1\n        , endPoint = p2\n        , radius = 0.5 -- too small!\n        , sweptAngle = Arc2d.smallPositive\n        }\n    --> Nothing\n\nNote that this means it is dangerous to use this function to construct 180\ndegree arcs (half circles), since in this case due to numerical roundoff the\ndistance between the two given points may appear to be slightly more than twice\nthe given radius. In this case it is safer to use a more specialized approach,\nsuch as\n\n    halfCircle =\n        Arc2d.with\n            { startPoint = firstPoint\n            , centerPoint =\n                Point2d.midpoint firstPoint secondPoint\n            , sweptAngle = degrees 180\n            }\n\n(Use `sweptAngle = degrees -180` for a clockwise arc.)\n\n",
                "type": "{ startPoint : Point2d, endPoint : Point2d, radius : Float, sweptAngle : SweptAngle } -> Maybe Arc2d"
            },
            {
                "name": "largeNegative",
                "comment": " Flag used as argument to [`fromEndpoints`](#fromEndpoints).\n",
                "type": "SweptAngle"
            },
            {
                "name": "largePositive",
                "comment": " Flag used as argument to [`fromEndpoints`](#fromEndpoints).\n",
                "type": "SweptAngle"
            },
            {
                "name": "mirrorAcross",
                "comment": " Mirror an arc across a given axis.\n\n    Arc2d.mirrorAcross Axis2d.y exampleArc\n    --> Arc2d.with\n    -->     { startPoint =\n    -->         Point2d.fromCoordinates ( -3, 1 )\n    -->     , centerPoint =\n    -->         Point2d.fromCoordinates ( -1, 1 )\n    -->     , sweptAngle = degrees -90\n    -->     }\n\n",
                "type": "Axis2d -> Arc2d -> Arc2d"
            },
            {
                "name": "placeIn",
                "comment": " Take an arc considered to be defined in local coordinates relative to a\ngiven reference frame, and return that arc expressed in global coordinates.\n\n    localFrame =\n        Frame2d.atPoint (Point2d.fromCoordinates ( 1, 2 ))\n\n    Arc2d.placeIn localFrame exampleArc\n    --> Arc2d.with\n    -->     { startPoint =\n    -->         Point2d.fromCoordinates ( 4, 3 )\n    -->     , centerPoint =\n    -->         Point2d.fromCoordinates ( 2, 3 )\n    -->     , sweptAngle = degrees 90\n    -->     }\n\n",
                "type": "Frame2d -> Arc2d -> Arc2d"
            },
            {
                "name": "pointOn",
                "comment": " Get the point along an arc at a given parameter value. A parameter value of\n0 corresponds to the start point of the arc and a value of 1 corresponds to the\nend point.\n\n    Arc2d.pointOn exampleArc 0.5\n    --> Point2d.fromCoordinates ( 2.4142, 2.4142 )\n\n",
                "type": "Arc2d -> Float -> Point2d"
            },
            {
                "name": "radius",
                "comment": " Get the radius of an arc.\n\n    Arc2d.radius exampleArc\n    --> 2\n\n",
                "type": "Arc2d -> Float"
            },
            {
                "name": "relativeTo",
                "comment": " Take an arc defined in global coordinates, and return it expressed in local\ncoordinates relative to a given reference frame.\n\n    localFrame =\n        Frame2d.atPoint (Point2d.fromCoordinates ( 1, 2 ))\n\n    Arc2d.relativeTo localFrame exampleArc\n    --> Arc2d.with\n    -->     { startPoint =\n    -->         Point2d.fromCoordinates ( 2, -1 )\n    -->     , centerPoint =\n    -->         Point2d.fromCoordinates ( 0, -1 )\n    -->     , sweptAngle = degrees 90\n    -->     }\n\n",
                "type": "Frame2d -> Arc2d -> Arc2d"
            },
            {
                "name": "reverse",
                "comment": " Reverse the direction of an arc, so that the start point becomes the end\npoint and vice versa.\n\n    Arc2d.reverse exampleArc\n    --> Arc2d.with\n    -->     { startPoint =\n    -->         Point2d.fromCoordinates ( 1, 3 )\n    -->     , centerPoint =\n    -->         Point2d.fromCoordinates ( 1, 1 )\n    -->     , sweptAngle = degrees -90\n    -->     }\n\n",
                "type": "Arc2d -> Arc2d"
            },
            {
                "name": "rotateAround",
                "comment": " Rotate an arc around a given point by a given angle.\n\n    Arc2d.rotateAround Point2d.origin (degrees 90)\n    --> Arc2d.with\n    -->     { startPoint =\n    -->         Point2d.fromCoordinates ( -1, 3 )\n    -->     , centerPoint =\n    -->         Point2d.fromCoordinates ( -1, 1 )\n    -->     , sweptAngle = degrees 90\n    -->     }\n\n",
                "type": "Point2d -> Float -> Arc2d -> Arc2d"
            },
            {
                "name": "scaleAbout",
                "comment": " Scale an arc about a given point by a given scale.\n\n    point =\n        Point2d.fromCoordinates ( 0, 1 )\n\n    Arc2d.scaleAbout point 2 exampleArc\n    --> Arc2d.with\n    -->     { startPoint =\n    -->         Point2d.fromCoordinates ( 6, 1 )\n    -->     , centerPoint =\n    -->         Point2d.fromCoordinates ( 2, 1 )\n    -->     , sweptAngle = degrees 90\n    -->     }\n\n",
                "type": "Point2d -> Float -> Arc2d -> Arc2d"
            },
            {
                "name": "smallNegative",
                "comment": " Flag used as argument to [`fromEndpoints`](#fromEndpoints).\n",
                "type": "SweptAngle"
            },
            {
                "name": "smallPositive",
                "comment": " Flag used as argument to [`fromEndpoints`](#fromEndpoints).\n",
                "type": "SweptAngle"
            },
            {
                "name": "startPoint",
                "comment": " Get the start point of an arc.\n\n    Arc2d.startPoint exampleArc\n    --> Point2d.fromCoordinates ( 3, 1 )\n\n",
                "type": "Arc2d -> Point2d"
            },
            {
                "name": "sweptAngle",
                "comment": " Get the swept angle of an arc in radians.\n\n    Arc2d.sweptAngle exampleArc\n    --> 1.5708\n\nThe result will be positive for a counterclockwise arc and negative for a\nclockwise one.\n\n",
                "type": "Arc2d -> Float"
            },
            {
                "name": "throughPoints",
                "comment": " Attempt to construct an arc that starts at the first given point, passes\nthrough the second given point and ends at the third given point. If the three\npoints are collinear, returns `Nothing`.\n\n    Arc2d.throughPoints\n        ( Point2d.origin\n        , Point2d.fromCoordinates ( 1, 0 )\n        , Point2d.fromCoordinates ( 0, 1 )\n        )\n    --> Just\n    -->     (Arc2d.with\n    -->         { centerPoint =\n    -->             Point2d.fromCoordinates ( 0.5, 0.5 )\n    -->         , startPoint = Point2d.origin\n    -->         , sweptAngle = degrees 270\n    -->         }\n    -->     )\n\n    Arc2d.throughPoints\n        ( Point2d.fromCoordinates ( 1, 0 )\n        , Point2d.origin\n        , Point2d.fromCoordinates ( 0, 1 )\n        )\n    --> Just\n    -->     (Arc2d.with\n    -->         { centerPoint =\n    -->             Point2d.fromCoordinates ( 0.5, 0.5 )\n    -->         , startPoint =\n    -->             Point2d.fromCoordinates ( 1, 0 )\n    -->         , sweptAngle = degrees -180\n    -->         }\n    -->     )\n\n    Arc2d.throughPoints\n        ( Point2d.origin\n        , Point2d.fromCoordinates ( 1, 0 )\n        , Point2d.fromCoordinates ( 2, 0 )\n        )\n    --> Nothing\n\n    Arc2d.throughPoints\n        ( Point2d.origin\n        , Point2d.origin\n        , Point2d.fromCoordinates ( 1, 0 )\n        )\n    --> Nothing\n\n",
                "type": "( Point2d, Point2d, Point2d ) -> Maybe Arc2d"
            },
            {
                "name": "toPolyline",
                "comment": " Approximate an arc as a polyline, within the specified tolerance.\n\n    Arc2d.toPolyline 0.1 exampleArc\n    --> Polyline2d.fromVertices\n    -->     [ Point2d.fromCoordinates ( 3, 1 )\n    -->     , Point2d.fromCoordinates ( 2.732, 2 )\n    -->     , Point2d.fromCoordinates ( 2, 2.732 )\n    -->     , Point2d.fromCoordinates ( 1, 3 )\n    -->     ]\n\nA tolerance of zero will be treated as infinity (a single line segment will be\nreturned).\n\n",
                "type": "Float -> Arc2d -> Polyline2d"
            },
            {
                "name": "translateBy",
                "comment": " Translate an arc by a given displacement.\n\n    displacement =\n        Vector2d.fromComponents ( 2, 3 )\n\n    Arc2d.translateBy displacement exampleArc\n    --> Arc2d.with\n    -->     { startPoint =\n    -->         Point2d.fromCoordinates ( 5, 4 )\n    -->     , centerPoint =\n    -->         Point2d.fromCoordinates ( 3, 4 )\n    -->     , sweptAngle = degrees 90\n    -->     }\n\n",
                "type": "Vector2d -> Arc2d -> Arc2d"
            },
            {
                "name": "with",
                "comment": " Construct an arc from its center point, start point, and swept angle:\n\n    exampleArc =\n        Arc2d.with\n            { centerPoint =\n                Point2d.fromCoordinates ( 1, 1 )\n            , startPoint =\n                Point2d.fromCoordinates ( 3, 1 )\n            , sweptAngle = degrees 90\n            }\n\n    Arc2d.endPoint exampleArc\n    --> Point2d.fromCoordinates ( 1, 3 )\n\nA positive swept angle means that the arc is formed by rotating the start point\ncounterclockwise around the center point. A negative swept angle results in\na clockwise arc instead.\n\n",
                "type": "{ centerPoint : Point2d, startPoint : Point2d, sweptAngle : Float } -> Arc2d"
            }
        ],
        "binops": []
    },
    {
        "name": "OpenSolid.Polygon2d",
        "comment": " <img src=\"https://opensolid.github.io/images/geometry/icons/polygon2d.svg\" alt=\"Polygon2d\" width=\"160\">\n\nA `Polygon2d` represents a closed polygon in 2D, and is defined by a list of\nvertices. This module contains a variety of polygon-related functionality, such\nas\n\n  - Computing the perimeter and area of polygons\n  - Scaling, rotating, translating and mirroring polygons\n  - Converting polygons between different coordinate systems\n\n@docs Polygon2d\n\n\n# Constructors\n\n@docs fromVertices\n\n\n# Properties\n\n@docs vertices, edges, perimeter, area, clockwiseArea, counterclockwiseArea, boundingBox\n\n\n# Transformations\n\nTransforming a polygon is equivalent to transforming each of its vertices.\n\n@docs scaleAbout, rotateAround, translateBy, mirrorAcross, mapVertices\n\n\n# Coordinate conversions\n\n@docs relativeTo, placeIn\n\n",
        "unions": [],
        "aliases": [
            {
                "name": "Polygon2d",
                "comment": " ",
                "args": [],
                "type": "Polygon2d"
            }
        ],
        "values": [
            {
                "name": "area",
                "comment": " Get the area of a polygon. This value will never be negative.\n\n    Polygon2d.area rectangle\n    --> 2\n\n",
                "type": "Polygon2d -> Float"
            },
            {
                "name": "boundingBox",
                "comment": " Get the minimal bounding box containing a given polygon. Returns `Nothing`\nif the polygon has no vertices.\n\n    Polygon2d.boundingBox rectangle\n    --> Just\n    -->     (BoundingBox2d.with\n    -->         { minX = 1\n    -->         , maxX = 3\n    -->         , minY = 1\n    -->         , maxY = 2\n    -->         }\n    -->     )\n\n",
                "type": "Polygon2d -> Maybe BoundingBox2d"
            },
            {
                "name": "clockwiseArea",
                "comment": " Get the signed area of a polygon, with polygons with vertices in clockwise\norder considered to have positive area and polygons with vertices in\ncounterclockwise order considered to have negative area.\n\n    Polygon2d.clockwiseArea rectangle\n    --> -6\n\n",
                "type": "Polygon2d -> Float"
            },
            {
                "name": "counterclockwiseArea",
                "comment": " Get the signed area of a polygon, with polygons with vertices in\ncounterclockwise order considered to have positive area and polygons with\nvertices in clockwise order considered to have negative area.\n\n    Polygon2d.counterclockwiseArea rectangle\n    --> 6\n\n",
                "type": "Polygon2d -> Float"
            },
            {
                "name": "edges",
                "comment": " Get the edges of a polygon. This will include an edge from the last point\nback to the first point.\n\n    Polygon2d.edges rectangle\n    --> [ LineSegment2d.fromEndpoints\n    -->     ( Point2d.fromCoordinates ( 1, 1 )\n    -->     , Point2d.fromCoordinates ( 3, 1 )\n    -->     )\n    --> , LineSegment2d.fromEndpoints\n    -->     ( Point2d.fromCoordinates ( 3, 1 )\n    -->     , Point2d.fromCoordinates ( 3, 2 )\n    -->     )\n    --> , LineSegment2d.fromEndpoints\n    -->     ( Point2d.fromCoordinates ( 3, 2 )\n    -->     , Point2d.fromCoordinates ( 1, 2 )\n    -->     )\n    --> , LineSegment2d.fromEndpoints\n    -->     ( Point2d.fromCoordinates ( 1, 2 )\n    -->     , Point2d.fromCoordinates ( 1, 1 )\n    -->     )\n    --> ]\n\n",
                "type": "Polygon2d -> List LineSegment2d"
            },
            {
                "name": "fromVertices",
                "comment": " Construct a polygon from a list of its vertices:\n\n    rectangle =\n        Polygon2d.fromVertices\n            [ Point2d.fromCoordinates ( 1, 1 )\n            , Point2d.fromCoordinates ( 3, 1 )\n            , Point2d.fromCoordinates ( 3, 2 )\n            , Point2d.fromCoordinates ( 1, 2 )\n            ]\n\nThe last vertex is implicitly considered to be connected back to the first\nvertex (you do not have to close the polygon explicitly).\n\n",
                "type": "List Point2d -> Polygon2d"
            },
            {
                "name": "mapVertices",
                "comment": " Transform each vertex of a polygon by the given function. All other\ntransformations can be defined in terms of `mapVertices`; for example,\n\n    Polygon2d.mirrorAcross axis\n\nis equivalent to\n\n    Polygon2d.mapVertices (Point2d.mirrorAcross axis)\n\n",
                "type": "(Point2d -> Point2d) -> Polygon2d -> Polygon2d"
            },
            {
                "name": "mirrorAcross",
                "comment": " Mirror a polygon across the given axis.\n\n    Polygon2d.mirrorAcross Axis2d.x rectangle\n    --> Polygon2d.fromVertices\n    -->     [ Point2d.fromCoordinates ( 1, -1 )\n    -->     , Point2d.fromCoordinates ( 3, -1 )\n    -->     , Point2d.fromCoordinates ( 3, -2 )\n    -->     , Point2d.fromCoordinates ( 1, -2 )\n    -->     ]\n\nNote that if a polygon's vertices were in counterclockwise order before\nmirroring, they will be in clockwise order afterward, and vice versa.\n\n",
                "type": "Axis2d -> Polygon2d -> Polygon2d"
            },
            {
                "name": "perimeter",
                "comment": " Get the perimeter of a polygon (the sum of the lengths of its edges).\n\n    Polygon2d.perimeter rectangle\n    --> 6\n\n",
                "type": "Polygon2d -> Float"
            },
            {
                "name": "placeIn",
                "comment": " Take a polygon considered to be defined in local coordinates relative\nto a given reference frame, and return that polygon expressed in global\ncoordinates.\n\n    localFrame =\n        Frame2d.atPoint (Point2d.fromCoordinates ( 1, 2 ))\n\n    Polygon2d.placeIn localFrame rectangle\n    --> Polygon2d.fromVertices\n    -->     [ Point2d.fromCoordinates ( 2, 3 )\n    -->     , Point2d.fromCoordinates ( 4, 3 )\n    -->     , Point2d.fromCoordinates ( 4, 4 )\n    -->     , Point2d.fromCoordinates ( 2, 4 )\n    -->     ]\n\n",
                "type": "Frame2d -> Polygon2d -> Polygon2d"
            },
            {
                "name": "relativeTo",
                "comment": " Take a polygon defined in global coordinates, and return it expressed\nin local coordinates relative to a given reference frame.\n\n    localFrame =\n        Frame2d.atPoint (Point2d.fromCoordinates ( 1, 2 ))\n\n    Polygon2d.relativeTo localFrame rectangle\n    --> Polygon2d.fromVertices\n    -->     [ Point2d.fromCoordinates ( 0, -1 )\n    -->     , Point2d.fromCoordinates ( 2, -1 )\n    -->     , Point2d.fromCoordinates ( 2, 0 )\n    -->     , Point2d.fromCoordinates ( 0, 0 )\n    -->     ]\n\n",
                "type": "Frame2d -> Polygon2d -> Polygon2d"
            },
            {
                "name": "rotateAround",
                "comment": " Rotate a polygon around the given center point counterclockwise by the given\nangle (in radians).\n\n    rectangle\n        |> Polygon2d.rotateAround Point2d.origin\n            (degrees 90)\n    --> Polygon2d.fromVertices\n    -->     [ Point2d.fromCoordinates ( -1, 1 )\n    -->     , Point2d.fromCoordinates ( -1, 3 )\n    -->     , Point2d.fromCoordinates ( -2, 3 )\n    -->     , Point2d.fromCoordinates ( -2, 1 )\n    -->     ]\n\n",
                "type": "Point2d -> Float -> Polygon2d -> Polygon2d"
            },
            {
                "name": "scaleAbout",
                "comment": " Scale a polygon about a given center point by a given scale.\n\n    point =\n        Point2d.fromCoordinates ( 2, 1 )\n\n    Polygon2d.scaleAbout point 2 rectangle\n    --> Polygon2d.fromVertices\n    -->     [ Point2d.fromCoordinates ( 0, 1 )\n    -->     , Point2d.fromCoordinates ( 4, 1 )\n    -->     , Point2d.fromCoordinates ( 4, 3 )\n    -->     , Point2d.fromCoordinates ( 0, 3 )\n    -->     ]\n\n",
                "type": "Point2d -> Float -> Polygon2d -> Polygon2d"
            },
            {
                "name": "translateBy",
                "comment": " Translate a polygon by the given displacement.\n\n    displacement =\n        Vector2d.fromComponents ( 2, 3 )\n\n    Polygon2d.translateBy displacement rectangle\n    --> Polygon2d.fromVertices\n    -->     [ Point2d.fromCoordinates ( 3, 4 )\n    -->     , Point2d.fromCoordinates ( 5, 4 )\n    -->     , Point2d.fromCoordinates ( 5, 5 )\n    -->     , Point2d.fromCoordinates ( 3, 5 )\n    -->     ]\n\n",
                "type": "Vector2d -> Polygon2d -> Polygon2d"
            },
            {
                "name": "vertices",
                "comment": " Get the vertices of a polygon.\n\n    Polygon2d.vertices rectangle\n    --> [ Point2d.fromCoordinates ( 1, 1 )\n    --> , Point2d.fromCoordinates ( 3, 1 )\n    --> , Point2d.fromCoordinates ( 3, 2 )\n    --> , Point2d.fromCoordinates ( 1, 2 )\n    --> ]\n\n",
                "type": "Polygon2d -> List Point2d"
            }
        ],
        "binops": []
    },
    {
        "name": "OpenSolid.SketchPlane3d",
        "comment": " <img src=\"https://opensolid.github.io/images/geometry/icons/sketchPlane3d.svg\" alt=\"SketchPlane3d\" width=\"160\">\n\nA `SketchPlane3d` represents a 2D planar coordinate system in 3D space, and is\ndefined by its origin point and X and Y directions (which are always\nperpendicular to each other). Sketch planes are the primary tool for converting\nback and forth between 2D and 3D coordinates:\n\n  - 3D geometry such as points, directions and line segments can be projected\n    _into_ a sketch plane, which effectively projects the geometry _onto_ the\n    sketch plane and then expresses the projected geometry _in_ 2D coordinates.\n  - 2D geometry can be place _onto_ a sketch plane to result in 3D geometry. For\n    example, a 2D point placed onto a sketch plane will result in a 3D point\n    _on_ that sketch plane that has the given 2D coordinate _in_ the sketch\n    plane.\n\nThis allows you to create algorithms that project from 3D into 2D, perform some\ncalculations in 2D, then convert the result back to 3D.\n\nMany 3D data types have `projectInto` functions that return the corresponding 2D\ndata type, and `on` functions for converting back to 3D. For example,\n[`Triangle3d.projectInto`](OpenSolid-Triangle3d#projectInto) returns a\n`Triangle2d` and [`Triangle3d.on`](OpenSolid-Triangle3d#on) returns a\n`Triangle3d`. These pairs of functions are almost, but not quite, inverses of\neach other:\n\n    triangle2d\n        |> Triangle3d.on sketchPlane\n        |> Triangle3d.projectInto sketchPlane\n\nwill just return the original `triangle2d` value (within roundoff error), while\n\n    triangle3d\n        |> Triangle3d.projectInto sketchPlane\n        |> Triangle3d.on sketchPlane\n\nis equivalent to\n\n    triangle3d\n        |> Triangle3d.projectOnto\n            (SketchPlane3d.plane sketchPlane)\n\n@docs SketchPlane3d\n\n\n# Constants\n\nThese predefined sketch planes all have the global origin point as their origin\npoint, and use the two indicated global axes as their X and Y axes. For example,\n\n    SketchPlane3d.originPoint SketchPlane3d.yz\n    --> Point3d.origin\n\n    SketchPlane3d.xDirection SketchPlane3d.yz\n    --> Direction3d.y\n\n    SketchPlane3d.yDirection SketchPlane3d.yz\n    --> Direction3d.z\n\n@docs xy, yx, yz, zy, zx, xz\n\n\n# Constructors\n\nSketch planes can also be constructed from `Frame3d` values using\n`Frame3d.xySketchPlane` etc.\n\n@docs with, on, throughPoints, fromPlane, unsafe\n\n\n# Properties\n\n@docs originPoint, xDirection, yDirection, normalDirection, xAxis, yAxis, normalAxis, plane\n\n\n# Transformations\n\n@docs offsetBy, flipX, flipY, moveTo, rotateAround, rotateAroundOwn, translateBy, translateAlongOwn, mirrorAcross\n\n\n# Coordinate conversions\n\n@docs relativeTo, placeIn\n\n",
        "unions": [],
        "aliases": [
            {
                "name": "SketchPlane3d",
                "comment": " ",
                "args": [],
                "type": "SketchPlane3d"
            }
        ],
        "values": [
            {
                "name": "flipX",
                "comment": " Flip the X direction of a sketch plane, leaving its Y direction and origin\npoint unchanged.\n\n    sketchPlane =\n        SketchPlane3d.flipX SketchPlane3d.yz\n\n    SketchPlane3d.originPoint sketchPlane\n    --> Point3d.origin\n\n    SketchPlane3d.xDirection sketchPlane\n    --> Direction3d.negativeY\n\n    SketchPlane3d.yDirection sketchPlane\n    --> Direction3d.z\n\n",
                "type": "SketchPlane3d -> SketchPlane3d"
            },
            {
                "name": "flipY",
                "comment": " Flip the Y direction of a sketch plane, leaving its X direction and origin\npoint unchanged.\n\n    sketchPlane =\n        SketchPlane3d.flipY SketchPlane3d.yz\n\n    SketchPlane3d.originPoint sketchPlane\n    --> Point3d.origin\n\n    SketchPlane3d.xDirection sketchPlane\n    --> Direction3d.y\n\n    SketchPlane3d.yDirection sketchPlane\n    --> Direction3d.negativeZ\n\n",
                "type": "SketchPlane3d -> SketchPlane3d"
            },
            {
                "name": "fromPlane",
                "comment": " Construct a SketchPlane3d from the given plane;\n\n    SketchPlane3d.fromPlane plane\n\nis equivalent to\n\n    SketchPlane3d.with\n        { originPoint = Plane3d.originPoint plane\n        , normalDirection = Plane3d.normalDirection plane\n        }\n\nNote that because the X and Y directions of the resulting sketch plane are\nchosen arbitrarily, conversions may not work exactly as you expect. For example,\nin the current implementation,\n\n    sketchPlane =\n        SketchPlane3d.fromPlane Plane3d.xy\n\nis not equal to `SketchPlane3d.xy` (although the two sketch planes have the same\norigin point and are coplanar):\n\n    SketchPlane3d.originPoint sketchPlane\n    --> Point3d.origin\n\n    SketchPlane3d.xDirection sketchPlane\n    --> Direction3d.negativeY\n\n    SketchPlane3d.yDirection sketchPlane\n    --> Direction3d.positiveX\n\n",
                "type": "Plane3d -> SketchPlane3d"
            },
            {
                "name": "mirrorAcross",
                "comment": " Mirror a sketch plane across a plane.\n\n    sketchPlane =\n        SketchPlane3d.yz\n            |> SketchPlane3d.moveTo\n                (Point2d.fromCoordinates ( 2, 1, 3 ))\n\n    mirroredSketchPlane =\n        SketchPlane3d.mirrorAcross Plane3d.xy sketchPlane\n\n    SketchPlane3d.originPoint sketchPlane\n    --> Point2d.fromCoordinates ( 2, 1, -3 )\n\n    SketchPlane3d.xDirection sketchPlane\n    --> Direction3d.y\n\n    SketchPlane3d.yDirection sketchPlane\n    --> Direction3d.negativeZ\n\n",
                "type": "Plane3d -> SketchPlane3d -> SketchPlane3d"
            },
            {
                "name": "moveTo",
                "comment": " Set the origin point of the given sketch plane to the given point, leaving\nits X and Y directions unchanged.\n\n    newOrigin =\n        Point3d.fromCoordinates ( 2, 1, 3 )\n\n    sketchPlane =\n        SketchPlane3d.moveTo newOrigin SketchPlane3d.yz\n\n    SketchPlane3d.originPoint sketchPlane\n    --> newOrigin\n\n    SketchPlane3d.xDirection sketchPlane\n    --> Direction3d.y\n\n    SketchPlane3d.yDirection sketchPlane\n    --> Direction3d.z\n\n",
                "type": "Point3d -> SketchPlane3d -> SketchPlane3d"
            },
            {
                "name": "normalAxis",
                "comment": " Get the normal axis to a sketch plane (the axis formed from the sketch\nplane's origin point and normal direction).\n\n    SketchPlane3d.normalAxis SketchPlane3d.xy\n    --> Axis3d.z\n\n    SketchPlane3d.normalAxis SketchPlane3d.xz\n    --> Axis3d.flip Axis3d.y\n\n",
                "type": "SketchPlane3d -> Axis3d"
            },
            {
                "name": "normalDirection",
                "comment": " Get the normal direction to a sketch plane. This is equal to the cross\nproduct of the sketch plane's X and Y directions.\n\n    SketchPlane3d.normalDirection SketchPlane3d.xy\n    --> Direction3d.z\n\n    SketchPlane3d.normalDirection SketchPlane3d.xz\n    --> Direction3d.negativeY\n\n",
                "type": "SketchPlane3d -> Direction3d"
            },
            {
                "name": "offsetBy",
                "comment": " Shift a sketch plane in its own normal direction by the given (signed)\ndistance.\n\n    SketchPlane3d.offsetBy -2.0 SketchPlane3d.xy\n        |> SketchPlane3d.originPoint\n    --> Point3d.fromCoordinates ( 0, 0, -2 )\n\n    SketchPlane3d.offsetBy 1.0 SketchPlane3d.zx\n        |> SketchPlane3d.originPoint\n    --> Point3d.fromCoordinates ( 0, 1, 0 )\n\n",
                "type": "Float -> SketchPlane3d -> SketchPlane3d"
            },
            {
                "name": "on",
                "comment": " Construct one sketch plane lying on another sketch plane, but with a\ndifferent origin point and X/Y directions. To do this, a `Frame2d` must be\nprovided that specifies the origin point and X/Y directions of the new sketch\nplane, in 2D coordinates within the existing sketch plane. Whew!\n\n    frame2d =\n        Frame2d.atPoint (Point2d.fromCoordinates ( 2, 3 ))\n            |> Frame2d.rotateBy (degrees -30)\n\n    sketchPlane =\n        SketchPlane3d.on SketchPlane3d.yz frame2d\n\n    SketchPlane3d.originPoint sketchPlane\n    --> Point3d.fromCoordinates ( 0, 2, 3 )\n\n    SketchPlane3d.xDirection sketchPlane\n    --> Direction3d.with\n    -->     { azimuth = degrees 90\n    -->     , elevation = degrees -30\n    -->     }\n\n    SketchPlane3d.yDirection sketchPlane\n    --> Direction3d.with\n    -->     { azimuth = degrees 90\n    -->     , elevation = degrees 60\n    -->     }\n\n",
                "type": "SketchPlane3d -> Frame2d -> SketchPlane3d"
            },
            {
                "name": "originPoint",
                "comment": " Get the origin point of a sketch plane.\n\n    SketchPlane3d.originPoint SketchPlane3d.xy\n    --> Point3d.origin\n\n",
                "type": "SketchPlane3d -> Point3d"
            },
            {
                "name": "placeIn",
                "comment": " Take a sketch plane defined in local coordinates relative to a given\nreference frame, and return that sketch plane expressed in global coordinates.\n",
                "type": "Frame3d -> SketchPlane3d -> SketchPlane3d"
            },
            {
                "name": "plane",
                "comment": " Get the plane of a sketch plane (the `Plane3d` with the same origin point\nand normal direction).\n\n    SketchPlane3d.plane SketchPlane3d.xy\n    --> Plane3d.xy\n\n    SketchPlane3d.plane SketchPlane3d.yx\n    --> Plane3d.flip Plane3d.xy\n\n",
                "type": "SketchPlane3d -> Plane3d"
            },
            {
                "name": "relativeTo",
                "comment": " Take a sketch plane defined in global coordinates, and return it expressed\nin local coordinates relative to a given reference frame.\n",
                "type": "Frame3d -> SketchPlane3d -> SketchPlane3d"
            },
            {
                "name": "rotateAround",
                "comment": " Rotate a sketch plane around an axis by a given angle (in radians). The\nsketch plane's origin point and X and Y directions will all be rotated around\nthe given axis.\n\n    SketchPlane3d.xy\n        |> SketchPlane3d.rotateAround Axis3d.x (degrees 90)\n    --> SketchPlane3d.xz\n\n",
                "type": "Axis3d -> Float -> SketchPlane3d -> SketchPlane3d"
            },
            {
                "name": "rotateAroundOwn",
                "comment": " Rotate a sketch plane around one of its own axes by a given angle (in\nradians).\n\nThe first argument is a function that returns the axis to rotate around, given\nthe current sketch plane. The majority of the time this will be either\n`SketchPlane3d.xAxis` or `SketchPlane3d.yAxis`.\n\nThis function is convenient when constructing sketch planes via a series of\ntransformations. For example,\n\n    sketchPlane =\n        SketchPlane3d.xy\n            |> SketchPlane3d.translateBy\n                (Vector3d.fromComponents ( 1, 0, 0 ))\n            |> SketchPlane3d.rotateAroundOwn\n                SketchPlane3d.yAxis\n                (degrees -45)\n\n    SketchPlane3d.originPoint sketchPlane\n    --> Point3d.fromCoordinates ( 1, 0, 0 )\n\n    SketchPlane3d.xDirection sketchPlane\n    --> Direction3d.with\n    -->     { azimuth = 0\n    -->     , elevation = degrees 45\n    -->     }\n\n    SketchPlane3d.yDirection sketchPlane\n    --> Direction3d.y\n\nNote that since the rotation was around the sketch plane's own Y axis (which\npasses through the sketch plane's origin point) instead of the global Y axis,\nthe origin point itself was not affected by the rotation.\n\n",
                "type": "(SketchPlane3d -> Axis3d) -> Float -> SketchPlane3d -> SketchPlane3d"
            },
            {
                "name": "throughPoints",
                "comment": " Attempt to construct a sketch plane that passes through the three given\npoints. Returns a sketch plane where:\n\n  - The origin point is the first given point\n  - The X direction is equal to the direction from the first given point to the\n    second\n  - The Y direction is chosen such that the third given point lies on the sketch\n    plane and has a positive Y coordinate within the sketch plane (that is, it\n    is on the positive Y side of the sketch plane's X axis)\n\nIf the three given points are collinear, returns `Nothing`.\n\n    SketchPlane3d.throughPoints\n        ( Point3d.fromCoordinates ( 2, 0, 0 )\n        , Point3d.fromCoordinates ( 3, 0, 0 )\n        , Point3d.fromCoordinates ( 4, 1, 1 )\n        )\n    --> Just sketchPlane\n\n    SketchPlane3d.originPoint sketchPlane\n    --> Point3d.fromCoordinates ( 2, 0, 0 )\n\n    SketchPlane3d.xDirection sketchPlane\n    --> Direction3d.x\n\n    SketchPlane3d.yDirection sketchPlane\n    --> Direction3d.with\n    -->     { azimuth = degrees 90\n    -->     , elevation = degrees 45\n    -->     }\n\n    SketchPlane3d.throughPoints\n        ( Point3d.fromCoordinates ( 2, 0, 0 )\n        , Point3d.fromCoordinates ( 3, 0, 0 )\n        , Point3d.fromCoordinates ( 4, 0, 0 )\n        )\n    --> Nothing\n\n",
                "type": "( Point3d, Point3d, Point3d ) -> Maybe SketchPlane3d"
            },
            {
                "name": "translateAlongOwn",
                "comment": " Translate a sketch plane along one of its own axes by a given distance.\n\nThe first argument is a function that returns the axis to translate along, given\nthe current sketch plane. The majority of the time this will be either\n`SketchPlane3d.xAxis` or `SketchPlane3d.yAxis`.\n\nThis function is convenient when constructing frames via a series of\ntransformations. For example,\n\n    sketchPlane =\n        SketchPlane3d.xy\n            |> SketchPlane3d.rotateAround\n                Axis3d.x\n                (degrees 45)\n            |> SketchPlane3d.translateAlongOwn\n                SketchPlane3d.yAxis\n                2\n\nmeans 'take the global XY sketch plane, rotate it around the global X axis by\n45 degrees, then translate the result 2 units along its own (rotated) Y axis',\nresulting in\n\n    SketchPlane3d.originPoint sketchPlane\n    --> Point3d.fromCoordinates ( 0, 1.4142, 1.4142 )\n\n    SketchPlane3d.xDirection sketchPlane\n    --> Direction3d.x\n\n    SketchPlane3d.yDirection sketchPlane\n    --> Direction3d.with\n    -->     { azimuth = degrees 90\n    -->     , elevation = degrees 45\n    -->     }\n\n",
                "type": "(SketchPlane3d -> Axis3d) -> Float -> SketchPlane3d -> SketchPlane3d"
            },
            {
                "name": "translateBy",
                "comment": " Translate a sketch plane by a given displacement.\n\n    displacement =\n        Vector3d.fromComponents ( 2, 1, 3 )\n\n    sketchPlane =\n        SketchPlane3d.xy\n            |> SketchPlane3d.translateBy displacement\n\n    SketchPlane3d.originPoint sketchPlane\n    --> Point3d.fromCoordinates ( 2, 1, 3 )\n\n    SketchPlane3d.xDirection sketchPlane\n    --> Direction3d.x\n\n    SketchPlane3d.yDirection sketchPlane\n    --> Direction3d.y\n\n",
                "type": "Vector3d -> SketchPlane3d -> SketchPlane3d"
            },
            {
                "name": "unsafe",
                "comment": " Construct a sketch plane directly from its origin point and X and Y\ndirections:\n\n    sketchPlane =\n        SketchPlane3d.unsafe\n            { originPoint =\n                Point3d.fromCoordinates ( 2, 1, 3 )\n            , xDirection = Direction3d.positiveY\n            , yDirection = Direction3d.negativeZ\n            }\n\nIf you construct a `SketchPlane3d` this way, **you must ensure that the X and Y\nbasis directions are perpendicular to each other**.\n\n",
                "type": "{ originPoint : Point3d, xDirection : Direction3d, yDirection : Direction3d } -> SketchPlane3d"
            },
            {
                "name": "with",
                "comment": " Construct a sketch plane with the given origin point and normal direction.\nThe X and Y basis directions of the sketch plane will:\n\n  - be perpendicular to each other,\n  - both be perpendicular to the given normal direction, and\n  - have a cross product equal to the given normal direction.\n\nThis is useful when constructing 'scratch' sketch planes where the specific X/Y\ndirections are unimportant.\n\n    sketchPlane =\n        SketchPlane3d.with\n            { originPoint = Point3d.origin\n            , normalDirection =\n                Direction3d.with\n                    { azimuth = 0\n                    , elevation = degrees 60\n                    }\n            }\n\n    SketchPlane3d.originPoint sketchPlane\n    --> Point3d.origin\n\n    SketchPlane3d.xDirection sketchPlane\n    --> Direction3d.with\n    -->     { azimuth = degrees 0\n    -->     , elevation = degrees -30\n    -->     }\n\n    SketchPlane3d.yDirection sketchPlane\n    --> Direction3d.y\n\n",
                "type": "{ originPoint : Point3d, normalDirection : Direction3d } -> SketchPlane3d"
            },
            {
                "name": "xAxis",
                "comment": " Get the X axis of a sketch plane. A 2D X coordinate within the sketch plane\ncorresponds to a distance along this axis in 3D.\n\n    SketchPlane3d.xAxis SketchPlane3d.zx\n    --> Axis3d.z\n\n",
                "type": "SketchPlane3d -> Axis3d"
            },
            {
                "name": "xDirection",
                "comment": " Get the X direction of a sketch plane (the direction of the sketch plane's\nX axis).\n\n    SketchPlane3d.xDirection SketchPlane3d.zx\n    --> Direction3d.z\n\n",
                "type": "SketchPlane3d -> Direction3d"
            },
            {
                "name": "xy",
                "comment": " A sketch plane formed from the global X and Y axes.\n",
                "type": "SketchPlane3d"
            },
            {
                "name": "xz",
                "comment": " A sketch plane formed from the global X and Z axes.\n",
                "type": "SketchPlane3d"
            },
            {
                "name": "yAxis",
                "comment": " Get the Y axis of a sketch plane. A 2D Y coordinate within the sketch plane\ncorresponds to a distance along this axis in 3D.\n\n    SketchPlane3d.yAxis SketchPlane3d.zx\n    --> Axis3d.x\n\n",
                "type": "SketchPlane3d -> Axis3d"
            },
            {
                "name": "yDirection",
                "comment": " Get the Y direction of a sketch plane (the direction of the sketch plane's\nY axis).\n\n    SketchPlane3d.yDirection SketchPlane3d.zx\n    --> Direction3d.x\n\n",
                "type": "SketchPlane3d -> Direction3d"
            },
            {
                "name": "yx",
                "comment": " A sketch plane formed from the global Y and X axes.\n",
                "type": "SketchPlane3d"
            },
            {
                "name": "yz",
                "comment": " A sketch plane formed from the global Y and Z axes.\n",
                "type": "SketchPlane3d"
            },
            {
                "name": "zx",
                "comment": " A sketch plane formed from the global Z and X axes.\n",
                "type": "SketchPlane3d"
            },
            {
                "name": "zy",
                "comment": " A sketch plane formed from the global Z and Y axes.\n",
                "type": "SketchPlane3d"
            }
        ],
        "binops": []
    },
    {
        "name": "OpenSolid.Polyline2d",
        "comment": " <img src=\"https://opensolid.github.io/images/geometry/icons/polyline2d.svg\" alt=\"Polyline2d\" width=\"160\">\n\nA `Polyline2d` represents a sequence of vertices in 2D connected by line\nsegments. This module contains a variety of polyline-related functionality, such\nas\n\n  - Computing the length of polylines\n  - Scaling, rotating, translating and mirroring polylines\n  - Converting polylines between different coordinate systems\n\n@docs Polyline2d\n\n\n# Constructors\n\n@docs fromVertices\n\n\n# Properties\n\n@docs vertices, segments, length, boundingBox\n\n\n# Transformations\n\nTransforming a polyline is equivalent to transforming each of its vertices.\n\n@docs scaleAbout, rotateAround, translateBy, mirrorAcross, projectOnto, mapVertices\n\n\n# Coordinate conversions\n\n@docs relativeTo, placeIn\n\n",
        "unions": [],
        "aliases": [
            {
                "name": "Polyline2d",
                "comment": " ",
                "args": [],
                "type": "Polyline2d"
            }
        ],
        "values": [
            {
                "name": "boundingBox",
                "comment": " Get the minimal bounding box containing a given polyline. Returns `Nothing`\nif the polyline has no vertices.\n\n    Polyline2d.boundingBox stepShape\n    --> Just\n    -->     (BoundingBox2d.with\n    -->         { minX = 0\n    -->         , maxX = 2\n    -->         , minY = 0\n    -->         , maxY = 1\n    -->         }\n    -->     )\n\n",
                "type": "Polyline2d -> Maybe BoundingBox2d"
            },
            {
                "name": "fromVertices",
                "comment": " Construct a polyline from a list of vertices:\n\n    stepShape =\n        Polyline2d.fromVertices\n            [ Point2d.fromCoordinates ( 0, 0 )\n            , Point2d.fromCoordinates ( 1, 0 )\n            , Point2d.fromCoordinates ( 1, 1 )\n            , Point2d.fromCoordinates ( 2, 1 )\n            ]\n\n",
                "type": "List Point2d -> Polyline2d"
            },
            {
                "name": "length",
                "comment": " Get the overall length of a polyline (the sum of the lengths of its\nsegments).\n\n    Polyline2d.length stepShape\n    --> 3\n\n",
                "type": "Polyline2d -> Float"
            },
            {
                "name": "mapVertices",
                "comment": " Transform each vertex of a polyline by the given function. All other\ntransformations can be defined in terms of `mapVertices`; for example,\n\n    Polyline2d.mirrorAcross axis\n\nis equivalent to\n\n    Polyline2d.mapVertices (Point2d.mirrorAcross axis)\n\n",
                "type": "(Point2d -> Point2d) -> Polyline2d -> Polyline2d"
            },
            {
                "name": "mirrorAcross",
                "comment": " Mirror a polyline across the given axis.\n\n    Polyline2d.mirrorAcross Axis2d.x stepShape\n    --> Polyline2d.fromVertices\n    -->     [ Point2d.fromCoordinates ( 0, 0 )\n    -->     , Point2d.fromCoordinates ( 1, 0 )\n    -->     , Point2d.fromCoordinates ( 1, -1 )\n    -->     , Point2d.fromCoordinates ( 2, -1 )\n    -->     ]\n\n",
                "type": "Axis2d -> Polyline2d -> Polyline2d"
            },
            {
                "name": "placeIn",
                "comment": " Take a polyline considered to be defined in local coordinates relative\nto a given reference frame, and return that polyline expressed in global\ncoordinates.\n\n    localFrame =\n        Frame2d.atPoint (Point2d.fromCoordinates ( 1, 2 ))\n\n    Polyline2d.placeIn localFrame stepShape\n    --> Polyline2d.fromVertices\n    -->     [ Point2d.fromCoordinates ( 1, 2 )\n    -->     , Point2d.fromCoordinates ( 2, 2 )\n    -->     , Point2d.fromCoordinates ( 2, 3 )\n    -->     , Point2d.fromCoordinates ( 3, 3 )\n    -->     ]\n\n",
                "type": "Frame2d -> Polyline2d -> Polyline2d"
            },
            {
                "name": "projectOnto",
                "comment": " Project (flatten) a polyline onto the given axis.\n\n    Polyline2d.projectOnto Axis2d.x stepShape\n    --> Polyline2d.fromVertices\n    -->     [ Point2d.fromCoordinates ( 0, 0 )\n    -->     , Point2d.fromCoordinates ( 1, 0 )\n    -->     , Point2d.fromCoordinates ( 1, 0 )\n    -->     , Point2d.fromCoordinates ( 2, 0 )\n    -->     ]\n\n",
                "type": "Axis2d -> Polyline2d -> Polyline2d"
            },
            {
                "name": "relativeTo",
                "comment": " Take a polyline defined in global coordinates, and return it expressed\nin local coordinates relative to a given reference frame.\n\n    localFrame =\n        Frame2d.atPoint (Point2d.fromCoordinates ( 1, 2 ))\n\n    Polyline2d.relativeTo localFrame stepShape\n    --> Polyline2d.fromVertices\n    -->     [ Point2d.fromCoordinates ( -1, -2 )\n    -->     , Point2d.fromCoordinates ( 0, -2 )\n    -->     , Point2d.fromCoordinates ( 0, -1 )\n    -->     , Point2d.fromCoordinates ( 1, -1 )\n    -->     ]\n\n",
                "type": "Frame2d -> Polyline2d -> Polyline2d"
            },
            {
                "name": "rotateAround",
                "comment": " Rotate a polyline around the given center point counterclockwise by the\ngiven angle (in radians).\n\n    stepShape\n        |> Polyline2d.rotateAround Point2d.origin\n            (degrees 90)\n    --> Polyline2d.fromVertices\n    -->     [ Point2d.fromCoordinates ( 0, 0 )\n    -->     , Point2d.fromCoordinates ( 0, 1 )\n    -->     , Point2d.fromCoordinates ( -1, 1 )\n    -->     , Point2d.fromCoordinates ( -1, 2 )\n    -->     ]\n\n",
                "type": "Point2d -> Float -> Polyline2d -> Polyline2d"
            },
            {
                "name": "scaleAbout",
                "comment": " Scale a polyline about a given center point by a given scale.\n\n    point =\n        Point2d.fromCoordinates ( 1, 0 )\n\n    Polyline2d.scaleAbout point 2 stepShape\n    --> Polyline2d.fromVertices\n    -->     [ Point2d.fromCoordinates ( -1, 0 )\n    -->     , Point2d.fromCoordinates ( 1, 0 )\n    -->     , Point2d.fromCoordinates ( 1, 2 )\n    -->     , Point2d.fromCoordinates ( 3, 2 )\n    -->     ]\n\n",
                "type": "Point2d -> Float -> Polyline2d -> Polyline2d"
            },
            {
                "name": "segments",
                "comment": " Get the individual segments of a polyline.\n\n    Polyline2d.segments stepShape\n    --> [ LineSegment2d.fromEndpoints\n    -->     ( Point2d.fromCoordinates ( 0, 0 )\n    -->     , Point2d.fromCoordinates ( 1, 0 )\n    -->     )\n    --> , LineSegment2d.fromEndpoints\n    -->     ( Point2d.fromCoordinates ( 1, 0 )\n    -->     , Point2d.fromCoordinates ( 1, 1 )\n    -->     )\n    --> , LineSegment2d.fromEndpoints\n    -->     ( Point2d.fromCoordinates ( 1, 1 )\n    -->     , Point2d.fromCoordinates ( 2, 1 )\n    -->     )\n    --> ]\n\n",
                "type": "Polyline2d -> List LineSegment2d"
            },
            {
                "name": "translateBy",
                "comment": " Translate a polyline by the given displacement.\n\n    displacement =\n        Vector2d.fromComponents ( 2, 3 )\n\n    Polyline2d.translateBy displacement stepShape\n    --> Polyline2d.fromVertices\n    -->     [ Point2d.fromCoordinates ( 2, 3 )\n    -->     , Point2d.fromCoordinates ( 3, 3 )\n    -->     , Point2d.fromCoordinates ( 3, 4 )\n    -->     , Point2d.fromCoordinates ( 4, 4 )\n    -->     ]\n\n",
                "type": "Vector2d -> Polyline2d -> Polyline2d"
            },
            {
                "name": "vertices",
                "comment": " Get the vertices of a polyline.\n\n    Polyline2d.vertices stepShape\n    --> [ Point2d.fromCoordinates ( 0, 0 )\n    --> , Point2d.fromCoordinates ( 1, 0 )\n    --> , Point2d.fromCoordinates ( 1, 1 )\n    --> , Point2d.fromCoordinates ( 2, 1 )\n    --> ]\n\n",
                "type": "Polyline2d -> List Point2d"
            }
        ],
        "binops": []
    },
    {
        "name": "OpenSolid.Triangle2d",
        "comment": " <img src=\"https://opensolid.github.io/images/geometry/icons/triangle2d.svg\" alt=\"Triangle2d\" width=\"160\">\n\nA `Triangle2d` represents a triangle in 2D space, and is defined by its three\nvertices. This module contains triangle-related functionality such as:\n\n  - Finding the area and centroid of triangles\n  - Scaling, rotating, translating and mirroring triangles\n  - Converting triangles between different coordinate systems\n\n@docs Triangle2d\n\n\n# Constructors\n\n@docs fromVertices\n\n\n# Properties\n\n@docs vertices, edges, centroid, area, counterclockwiseArea, clockwiseArea, boundingBox, circumcircle\n\n\n# Queries\n\n@docs contains\n\n\n# Transformations\n\nTransforming a triangle is equivalent to transforming its vertices.\n\n@docs scaleAbout, rotateAround, translateBy, mirrorAcross, mapVertices\n\n\n# Coordinate conversions\n\nFunctions for transforming triangles between local and global coordinates in\ndifferent coordinate frames.\n\n@docs relativeTo, placeIn\n\n",
        "unions": [],
        "aliases": [
            {
                "name": "Triangle2d",
                "comment": " ",
                "args": [],
                "type": "Triangle2d"
            }
        ],
        "values": [
            {
                "name": "area",
                "comment": " Get the area of a triangle. The result will always be positive regardless of\nwhether the triangle's vertices are in clockwise or counterclockwise order.\n\n    Triangle2d.area exampleTriangle\n    --> 1.0\n\n",
                "type": "Triangle2d -> Float"
            },
            {
                "name": "boundingBox",
                "comment": " Get the minimal bounding box containing a given triangle.\n\n    Triangle2d.boundingBox exampleTriangle\n    --> BoundingBox2d.with\n    -->     { minX = 1\n    -->     , maxX = 2\n    -->     , minY = 1\n    -->     , maxY = 3\n    -->     }\n\n",
                "type": "Triangle2d -> BoundingBox2d"
            },
            {
                "name": "centroid",
                "comment": " Get the centroid (center of mass) of a triangle.\n\n    Triangle2d.centroid exampleTriangle\n    --> Point2d.fromCoordinates ( 1.3333, 1.6667 )\n\n",
                "type": "Triangle2d -> Point2d"
            },
            {
                "name": "circumcircle",
                "comment": " Attempt to find the circumcircle of a triangle, a circle that passes through\neach of the triangle's vertices;\n\n    Triangle2d.circumcircle triangle\n\nis equivalent to\n\n    Circle2d.throughPoints (Triangle2d.vertices triangle)\n\nIf the triangle is degenerate (its three vertices are collinear), returns\n`Nothing`.\n\n",
                "type": "Triangle2d -> Maybe Circle2d"
            },
            {
                "name": "clockwiseArea",
                "comment": " Get the signed area of a triangle, returning a positive value if the\ntriangle's vertices are in clockwise order and a negative value otherwise.\n\n    Triangle2d.clockwiseArea exampleTriangle\n    --> -1.0\n\n",
                "type": "Triangle2d -> Float"
            },
            {
                "name": "contains",
                "comment": " Check whether a given point is inside a given triangle.\n\n    interiorPoint =\n        Point2d.fromCoordinates ( 1.5, 1.5 )\n\n    Triangle2d.contains interiorPoint exampleTriangle\n    --> True\n\n    Triangle2d.contains Point2d.origin exampleTriangle\n    --> False\n\nIt does not matter whether the triangle's vertices are in clockwise or\ncounterclockwise order.\n\n",
                "type": "Point2d -> Triangle2d -> Bool"
            },
            {
                "name": "counterclockwiseArea",
                "comment": " Get the signed area of a triangle, returning a positive value if the\ntriangle's vertices are in counterclockwise order and a negative value\notherwise.\n\n    Triangle2d.counterclockwiseArea exampleTriangle\n    --> 1.0\n\n",
                "type": "Triangle2d -> Float"
            },
            {
                "name": "edges",
                "comment": " Get the edges of a triangle: from the first vertex to the second, from the\nsecond to the third, and from the third back to the first.\n\n    ( e1, e2, e3 ) =\n        Triangle2d.edges exampleTriangle\n\n\n    --> e1 =\n    -->     LineSegment2d.fromEndpoints\n    -->         ( Point2d.fromCoordinates ( 1, 1 )\n    -->         , Point2d.fromCoordinates ( 2, 1 )\n    -->         )\n    -->\n    --> e2 =\n    -->     LineSegment2d.fromEndpoints\n    -->         ( Point2d.fromCoordinates ( 2, 1 )\n    -->         , Point2d.fromCoordinates ( 1, 3 )\n    -->         )\n    -->\n    --> e3 =\n    -->     LineSegment2d.fromEndpoints\n    -->         ( Point2d.fromCoordinates ( 1, 3 )\n    -->         , Point2d.fromCoordinates ( 1, 1 )\n    -->         )\n\n",
                "type": "Triangle2d -> ( LineSegment2d, LineSegment2d, LineSegment2d )"
            },
            {
                "name": "fromVertices",
                "comment": " Construct a triangle from its three vertices:\n\n    exampleTriangle =\n        Triangle2d.fromVertices\n            ( Point2d.fromCoordinates ( 1, 1 )\n            , Point2d.fromCoordinates ( 2, 1 )\n            , Point2d.fromCoordinates ( 1, 3 )\n            )\n\n",
                "type": "( Point2d, Point2d, Point2d ) -> Triangle2d"
            },
            {
                "name": "mapVertices",
                "comment": " Transform each vertex of a triangle by a given function and create a new\ntriangle from the resulting points. Most other transformation functions can be\ndefined in terms of `mapVertices`; for example,\n\n    Triangle2d.mirrorAcross axis\n\nis equivalent to\n\n    Triangle2d.mapVertices (Point2d.mirrorAcross axis)\n\n",
                "type": "(Point2d -> Point2d) -> Triangle2d -> Triangle2d"
            },
            {
                "name": "mirrorAcross",
                "comment": " Mirror a triangle across a given axis.\n\n    Triangle2d.mirrorAcross Axis2d.y exampleTriangle\n    --> Triangle2d.fromVertices\n    -->     ( Point2d.fromCoordinates ( -1, 1 )\n    -->     , Point2d.fromCoordinates ( -2, 1 )\n    -->     , Point2d.fromCoordinates ( -1, 3 )\n    -->     )\n\nNote that mirroring a triangle will result in its 'winding direction' being\nflipped - if the triangle's vertices were in counterclockwise order before\nmirroring, they will be in clockwise order afterwards and vice versa.\n\n",
                "type": "Axis2d -> Triangle2d -> Triangle2d"
            },
            {
                "name": "placeIn",
                "comment": " Take a triangle considered to be defined in local coordinates relative to a\ngiven reference frame, and return that triangle expressed in global coordinates.\n\n    localFrame =\n        Frame2d.atPoint (Point2d.fromCoordinates ( 1, 2 ))\n\n    Triangle2d.placeIn localFrame exampleTriangle\n    --> Triangle2d.fromVertices\n    -->     ( Point2d.fromCoordinates ( 2, 3 )\n    -->     , Point2d.fromCoordinates ( 3, 3 )\n    -->     , Point2d.fromCoordinates ( 2, 5 )\n    -->     )\n\n",
                "type": "Frame2d -> Triangle2d -> Triangle2d"
            },
            {
                "name": "relativeTo",
                "comment": " Take a triangle defined in global coordinates, and return it expressed\nin local coordinates relative to a given reference frame.\n\n    localFrame =\n        Frame2d.atPoint (Point2d.fromCoordinates ( 1, 2 ))\n\n    Triangle2d.relativeTo localFrame exampleTriangle\n    --> Triangle2d.fromVertices\n    -->     ( Point2d.fromCoordinates ( 0, -1 )\n    -->     , Point2d.fromCoordinates ( 1, -1 )\n    -->     , Point2d.fromCoordinates ( 0, 1 )\n    -->     )\n\n",
                "type": "Frame2d -> Triangle2d -> Triangle2d"
            },
            {
                "name": "rotateAround",
                "comment": " Rotate a triangle around a given point by a given angle (in radians).\n\n    exampleTriangle\n        |> Triangle2d.rotateAround Point2d.origin\n            (degrees 90)\n    --> Triangle2d.fromVertices\n    -->     ( Point2d.fromCoordinates ( -1, 1 )\n    -->     , Point2d.fromCoordinates ( -1, 2 )\n    -->     , Point2d.fromCoordinates ( -3, 1 )\n    -->     )\n\n",
                "type": "Point2d -> Float -> Triangle2d -> Triangle2d"
            },
            {
                "name": "scaleAbout",
                "comment": " Scale a triangle about a given point by a given scale.\n\n    Triangle2d.scaleAbout Point2d.origin 2 exampleTriangle\n    --> Triangle2d.fromVertices\n    -->     ( Point2d.fromCoordinates ( 2, 2 )\n    -->     , Point2d.fromCoordinates ( 4, 2 )\n    -->     , Point2d.fromCoordinates ( 2, 6 )\n    -->     )\n\nNote that scaling by a negative value will result in the 'winding direction' of\nthe triangle being flipped - if the triangle's vertices were in counterclockwise\norder before the negative scaling, they will be in clockwise order afterwards\nand vice versa.\n\n",
                "type": "Point2d -> Float -> Triangle2d -> Triangle2d"
            },
            {
                "name": "translateBy",
                "comment": " Translate a triangle by a given displacement.\n\n    displacement =\n        Vector2d.fromComponents ( 2, -3 )\n\n    Triangle2d.translateBy displacement exampleTriangle\n    --> Triangle2d.fromVertices\n    -->     ( Point2d.fromCoordinates ( 3, -2 )\n    -->     , Point2d.fromCoordinates ( 4, -2 )\n    -->     , Point2d.fromCoordinates ( 3, 0 )\n    -->     )\n\n",
                "type": "Vector2d -> Triangle2d -> Triangle2d"
            },
            {
                "name": "vertices",
                "comment": " Get the vertices of a triangle.\n\n    ( p1, p2, p3 ) =\n        Triangle2d.vertices exampleTriangle\n\n\n    --> p1 = Point2d.fromCoordinates ( 1, 1 )\n    --> p2 = Point2d.fromCoordinates ( 2, 1 )\n    --> p3 = Point2d.fromCoordinates ( 1, 3 )\n\n",
                "type": "Triangle2d -> ( Point2d, Point2d, Point2d )"
            }
        ],
        "binops": []
    },
    {
        "name": "OpenSolid.EllipticalArc2d",
        "comment": " <img src=\"https://opensolid.github.io/images/geometry/icons/ellipticalArc2d.svg\" alt=\"EllipticalArc2d\" width=\"160\">\n\nAn `EllipticalArc2d` is a section of an `Ellipse2d` with a start and end point.\nThis module includes functionality for\n\n  - Constructing an elliptical arc from its center or end points\n  - Scaling, rotating, translating and mirroring elliptical arcs\n  - Evaluating points and derivative vectors along elliptical arcs\n  - Forming arc length parameterizations of elliptical arcs\n\nThe `startAngle` and `sweptAngle` values referred to below are not actually\nproper angles but instead refer to values of the [ellipse parameter](https://en.wikipedia.org/wiki/Ellipse#Parametric_representation).\nHowever, in simple cases you don't need to worry about the difference - if\n`startAngle` and `sweptAngle` are both multiples of 90 degrees, then you can\ntreat them as actual angles and everything will work out.\n\n@docs EllipticalArc2d\n\n\n# Constructors\n\n@docs with, fromEndpoints, SweptAngle, smallPositive, smallNegative, largePositive, largeNegative\n\n\n# Properties\n\n@docs startAngle, sweptAngle, startPoint, endPoint\n\nAll remaining properties of elliptical arcs are actually just properties of the\nunderlying ellipse; check out the [Ellipse2d](OpenSolid-Ellipse2d) module for\ndetails.\n\n@docs centerPoint, axes, xAxis, yAxis, xDirection, yDirection, xRadius, yRadius\n\n\n# Evaluation\n\n@docs pointOn, derivative\n\n\n# Transformations\n\n@docs reverse, scaleAbout, rotateAround, translateBy, mirrorAcross\n\n\n# Coordinate conversions\n\n@docs relativeTo, placeIn\n\n\n# Arc length parameterization\n\n@docs ArcLengthParameterized, arcLengthParameterized, arcLength, pointAlong, tangentAlong, arcLengthToParameterValue, parameterValueToArcLength\n\n\n# Low level\n\nLow level functionality that you are unlikely to need to use directly.\n\n@docs derivativeMagnitude, maxSecondDerivativeMagnitude\n\n",
        "unions": [
            {
                "name": "ArcLengthParameterized",
                "comment": " An elliptical arc that has been parameterized by arc length.\n",
                "args": [],
                "cases": []
            },
            {
                "name": "SweptAngle",
                "comment": " Argument type used in [`fromEndpoints`](#fromEndpoints).\n",
                "args": [],
                "cases": []
            }
        ],
        "aliases": [
            {
                "name": "EllipticalArc2d",
                "comment": " An elliptical arc in 2D.\n",
                "args": [],
                "type": "EllipticalArc2d"
            }
        ],
        "values": [
            {
                "name": "arcLength",
                "comment": " Find the total arc length of an elliptical arc. This will be accurate to\nwithin the tolerance given when calling `arcLengthParameterized`.\n\n    arcLength : Float\n    arcLength =\n        EllipticalArc2d.arcLength parameterizedArc\n\n    arcLength\n    --> 2.4221\n\n",
                "type": "ArcLengthParameterized -> Float"
            },
            {
                "name": "arcLengthParameterized",
                "comment": " Build an arc length parameterization of the given elliptical arc, within\na given tolerance. Generally speaking, all operations on the resulting\n`ArcLengthParameterized` value will be accurate to within the given arc length\ntolerance.\n\n    tolerance =\n        1.0e-4\n\n    parameterizedArc =\n        EllipticalArc2d.arcLengthParameterized\n            tolerance\n            exampleArc\n\n",
                "type": "Float -> EllipticalArc2d -> ArcLengthParameterized"
            },
            {
                "name": "arcLengthToParameterValue",
                "comment": " Try to get the parameter value along an elliptical arc at a given arc\nlength. If the given arc length is less than zero or greater than the arc length\nof the arc, returns `Nothing`.\n\n    EllipticalArc2d.arcLengthToParameterValue\n        parameterizedArc\n        (arcLength / 2)\n    --> Just 0.5947\n\n",
                "type": "ArcLengthParameterized -> Float -> Maybe Float"
            },
            {
                "name": "axes",
                "comment": " ",
                "type": "EllipticalArc2d -> Frame2d"
            },
            {
                "name": "centerPoint",
                "comment": " ",
                "type": "EllipticalArc2d -> Point2d"
            },
            {
                "name": "derivative",
                "comment": " Get the deriative value at a point along an elliptical arc, based on a\nparameter that ranges from 0 to 1. A parameter value of 0 corresponds to the\nderivative at the start point of the arc and a value of 1 corresponds to the\nderivative at the end point.\n\n    EllipticalArc2d.derivative exampleArc 0\n    --> Vector2d.fromComponents ( 0, 1.5708 )\n\n    EllipticalArc2d.derivative exampleArc 0.5\n    --> Vector2d.fromComponents ( -2.2214, 1.1107 )\n\n    EllipticalArc2d.derivative exampleArc 1\n    --> Vector2d.fromComponents ( -3.1416, 0 )\n\n",
                "type": "EllipticalArc2d -> Float -> Vector2d"
            },
            {
                "name": "derivativeMagnitude",
                "comment": " ",
                "type": "EllipticalArc2d -> Float -> Float"
            },
            {
                "name": "endPoint",
                "comment": " Get the end point of an elliptical arc.\n\n    EllipticalArc2d.endPoint exampleArc\n    --> Point2d.fromCoordinates ( 0, 1 )\n\n",
                "type": "EllipticalArc2d -> Point2d"
            },
            {
                "name": "fromEndpoints",
                "comment": " Attempt to construct an elliptical arc from its endpoints, X direction, and\nX and Y radii. For any given valid set of these inputs, there are four possible\nsolutions, so you also need to specify which of the four solutions you want -\nwhether the swept angle of the arc should be less than or greater than 180\ndegrees, and whether the swept angle should be positive (counterclockwise) or\nnegative (clockwise).\n\nThe example below is interactive; try dragging either endpoint or the tip of the\nX direction (or the center point to move the whole arc), clicking on the X or Y\nradial lines and then scrolling to changet that radius, or clicking/tapping on\nthe various dashed arcs to switch what kind of swept angle to use.\n\n<iframe src=\"https://opensolid.github.io/geometry/2.1.0/doc/interactive/EllipticalArc2d/fromEndpoints.html\" style=\"width: 500px; height: 400px\" scrolling=no frameborder=0>\n`https://opensolid.github.io/geometry/2.1.0/doc/interactive/EllipticalArc2d/fromEndpoints.html`\n</iframe>\n\nThis function will return `Nothing` if no solution can found. Typically this\nmeans that the two endpoints are too far apart, but could also mean that one of\nthe specified radii was negative or zero, or the two given points were\ncoincident.\n\nThe behavior of this function is very close to [the SVG spec](https://www.w3.org/TR/SVG/implnote.html#ArcImplementationNotes),\nbut when 'out of range' parameters are given this function will simply return\n`Nothing` instead of attempting to degrade gracefully (for example, by\nincreasing X and Y radius slightly if the given endpoints are slightly too far\napart). Note that this means this function is dangerous to use for 180 degree\narcs, since then slight numerical roundoff can mean the difference between a\nsolution being found and not - for 180 degree arcs it is safer to use\n`EllipticalArc2d.with` instead.\n\n",
                "type": "{ startPoint : Point2d, endPoint : Point2d, xDirection : Direction2d, xRadius : Float, yRadius : Float, sweptAngle : SweptAngle } -> Maybe EllipticalArc2d"
            },
            {
                "name": "largeNegative",
                "comment": " Flag used as argument to [`fromEndpoints`](#fromEndpoints).\n",
                "type": "SweptAngle"
            },
            {
                "name": "largePositive",
                "comment": " Flag used as argument to [`fromEndpoints`](#fromEndpoints).\n",
                "type": "SweptAngle"
            },
            {
                "name": "maxSecondDerivativeMagnitude",
                "comment": " ",
                "type": "EllipticalArc2d -> Float"
            },
            {
                "name": "mirrorAcross",
                "comment": " Mirror an elliptical arc across a given axis.\n\n    mirroredArc =\n        exampleArc\n            |> EllipticalArc2d.mirrorAcross Axis2d.y\n\n    EllipticalArc2d.startPoint mirroredArc\n    --> Point2d.fromCoordinates ( -2, 0 )\n\n    EllipticalArc2d.endPoint mirroredArc\n    --> Point2d.fromCoordinates ( 0, 1 )\n\n",
                "type": "Axis2d -> EllipticalArc2d -> EllipticalArc2d"
            },
            {
                "name": "parameterValueToArcLength",
                "comment": " Get the arc length along an elliptical arc at a given parameter value. If\nthe given parameter value is less than zero or greater than one, returns\n`Nothing`.\n\n    EllipticalArc2d.parameterValueToArcLength\n        parameterizedArc\n        0.5\n    --> Just 0.9657\n\n",
                "type": "ArcLengthParameterized -> Float -> Maybe Float"
            },
            {
                "name": "placeIn",
                "comment": " Take an elliptical arc considered to be defined in local coordinates\nrelative to a given reference frame, and return that arc expressed in global\ncoordinates.\n\n    localFrame =\n        Frame2d.atPoint (Point2d.fromCoordinates ( 1, 2 ))\n\n    EllipticalArc2d.relativeTo localFrame exampleArc\n    --> EllipticalArc2d.with\n    -->     { centerPoint =\n    -->         Point2d.fromCoordinates ( 1, 2 )\n    -->     , xDirection = Direction2d.x\n    -->     , xRadius = 2\n    -->     , yRadius = 1\n    -->     , startAngle = 0\n    -->     , sweptAngle = degrees 90\n    -->     }\n\n",
                "type": "Frame2d -> EllipticalArc2d -> EllipticalArc2d"
            },
            {
                "name": "pointAlong",
                "comment": " Try to get the point along an elliptical arc at a given arc length. For\nexample, to get the true midpoint of `exampleArc`:\n\n    EllipticalArc2d.pointAlong parameterizedArc\n        (arcLength / 2)\n    --> Just (Point2d.fromCoordinates ( 1.1889, 0.8041 ))\n\nNote that this is not the same as evaulating at a parameter value of 0.5:\n\n    EllipticalArc2d.pointOn exampleArc 0.5\n    --> Point2d.fromCoordinates ( 1.4142, 0.7071 )\n\nIf the given arc length is less than zero or greater than the arc length of the\narc, `Nothing` is returned.\n\n",
                "type": "ArcLengthParameterized -> Float -> Maybe Point2d"
            },
            {
                "name": "pointOn",
                "comment": " Get a point along an elliptical arc, based on a parameter that ranges from 0\nto 1. A parameter value of 0 corresponds to the start point of the arc and a\nvalue of 1 corresponds to the end point.\n\n    EllipticalArc2d.pointOn exampleArc 0\n    --> Point2d.fromCoordinates ( 2, 0 )\n\n    EllipticalArc2d.pointOn exampleArc 0.5\n    --> Point2d.fromCoordinates ( 1.4142, 0.7071 )\n\n    EllipticalArc2d.pointOn exampleArc 1\n    --> Point2d.fromCoordinates ( 0, 1 )\n\n",
                "type": "EllipticalArc2d -> Float -> Point2d"
            },
            {
                "name": "relativeTo",
                "comment": " Take an elliptical arc defined in global coordinates, and return it expressed in\nlocal coordinates relative to a given reference frame.\n\n    localFrame =\n        Frame2d.atPoint (Point2d.fromCoordinates ( 1, 2 ))\n\n    EllipticalArc2d.relativeTo localFrame exampleArc\n    --> EllipticalArc2d.with\n    -->     { centerPoint =\n    -->         Point2d.fromCoordinates ( -1, -2 )\n    -->     , xDirection = Direction2d.x\n    -->     , xRadius = 2\n    -->     , yRadius = 1\n    -->     , startAngle = 0\n    -->     , sweptAngle = degrees 90\n    -->     }\n\n",
                "type": "Frame2d -> EllipticalArc2d -> EllipticalArc2d"
            },
            {
                "name": "reverse",
                "comment": " Reverse the direction of an elliptical arc, so that the start point becomes\nthe end point and vice versa. Does not change the shape of the arc or any\nproperties of the underlying ellipse.\n\n    EllipticalArc2d.reverse exampleArc\n    --> EllipticalArc2d.with\n    -->     { centerPoint = Point2d.origin\n    -->     , xDirection = Direction2d.x\n    -->     , xRadius = 2\n    -->     , yRadius = 1\n    -->     , startAngle = degrees 90\n    -->     , sweptAngle = degrees -90\n    -->     }\n\n",
                "type": "EllipticalArc2d -> EllipticalArc2d"
            },
            {
                "name": "rotateAround",
                "comment": " Rotate an elliptical arc around a given point by a given angle (in radians).\n\n    exampleArc\n        |> EllipticalArc2d.rotateAround Point2d.origin\n            (degrees 180)\n    --> EllipticalArc2d.with\n    -->     { centerPoint = Point2d.origin\n    -->     , xDirection = Direction2d.negativeX\n    -->     , xRadius = 2\n    -->     , yRadius = 1\n    -->     , startAngle = 0\n    -->     , sweptAngle = degrees 90\n    -->     }\n\n",
                "type": "Point2d -> Float -> EllipticalArc2d -> EllipticalArc2d"
            },
            {
                "name": "scaleAbout",
                "comment": " Scale an elliptical arc about a given point by a given scale.\n\n    exampleArc\n        |> EllipticalArc2d.scaleAbout Point2d.origin 3\n    --> EllipticalArc2d.with\n    -->     { centerPoint = Point2d.origin\n    -->     , xDirection = Direction2d.x\n    -->     , xRadius = 6\n    -->     , yRadius = 3\n    -->     , startAngle = 0\n    -->     , sweptAngle = degrees 90\n    -->     }\n\n",
                "type": "Point2d -> Float -> EllipticalArc2d -> EllipticalArc2d"
            },
            {
                "name": "smallNegative",
                "comment": " Flag used as argument to [`fromEndpoints`](#fromEndpoints).\n",
                "type": "SweptAngle"
            },
            {
                "name": "smallPositive",
                "comment": " Flag used as argument to [`fromEndpoints`](#fromEndpoints).\n",
                "type": "SweptAngle"
            },
            {
                "name": "startAngle",
                "comment": " The start angle of an elliptical arc is the value of the [ellipse parameter](https://en.wikipedia.org/wiki/Ellipse#Parametric_representation)\nat the start point of the arc.\n\n    EllipticalArc2d.startAngle exampleArc\n    --> 0\n\n",
                "type": "EllipticalArc2d -> Float"
            },
            {
                "name": "startPoint",
                "comment": " Get the start point of an elliptical arc.\n\n    EllipticalArc2d.startPoint exampleArc\n    --> Point2d.fromCoordinates ( 2, 0 )\n\n",
                "type": "EllipticalArc2d -> Point2d"
            },
            {
                "name": "sweptAngle",
                "comment": " The swept angle of an elliptical arc is the difference between values of the\n[ellipse parameter](https://en.wikipedia.org/wiki/Ellipse#Parametric_representation)\nat the start and end points of the arc.\n\n    EllipticalArc2d.sweptAngle exampleArc\n    --> degrees 90\n\n",
                "type": "EllipticalArc2d -> Float"
            },
            {
                "name": "tangentAlong",
                "comment": " Try to get the tangent direction along an elliptical arc at a given arc\nlength. To get the tangent direction at the midpoint of `exampleArc`:\n\n    EllipticalArc2d.tangentAlong parameterizedArc\n        (arcLength / 2)\n    --> Just (Direction2d.fromAngle (degrees 159.71))\n\nIf the given arc length is less than zero or greater than the arc length of the\narc (or if the derivative of the arc happens to be exactly zero at the given arc\nlength), `Nothing` is returned.\n\n",
                "type": "ArcLengthParameterized -> Float -> Maybe Direction2d"
            },
            {
                "name": "translateBy",
                "comment": " Translate an elliptical arc by a given displacement.\n\n    exampleArc\n        |> EllipticalArc2d.translateBy\n            (Vector2d.fromComponents ( 2, 3 ))\n    --> EllipticalArc2d.with\n    -->     { centerPoint =\n    -->         Point2d.fromCoordinates ( 2, 3 )\n    -->     , xDirection = Direction2d.x\n    -->     , xRadius = 2\n    -->     , yRadius = 1\n    -->     , startAngle = 0\n    -->     , sweptAngle = degrees 90\n    -->     }\n\n",
                "type": "Vector2d -> EllipticalArc2d -> EllipticalArc2d"
            },
            {
                "name": "with",
                "comment": " Construct an elliptical arc from its center point, X direction, X and Y\nradii, start angle and swept angle. Any negative sign on `xRadius` or `yRadius`\nwill be ignored (the absolute values will be used).\n\nFor example, to construct a simple 90 degree elliptical arc, you might use\n\n    exampleArc =\n        EllipticalArc2d.with\n            { centerPoint = Point2d.origin\n            , xDirection = Direction2d.x\n            , xRadius = 2\n            , yRadius = 1\n            , startAngle = 0\n            , sweptAngle = degrees 90\n            }\n\n![90 degree elliptical arc](https://opensolid.github.io/geometry/2.1.0/doc/images/EllipticalArc2d/with1.svg)\n\nTo make an inclined 180 degree elliptical arc, you might use\n\n    EllipticalArc2d.with\n        { centerPoint = Point2d.origin\n        , xDirection = Direction2d.fromAngle (degrees 30)\n        , xRadius = 2\n        , yRadius = 1\n        , startAngle = degrees -90\n        , sweptAngle = degrees 180\n        }\n\n![180 degree inclined elliptical arc](https://opensolid.github.io/geometry/2.1.0/doc/images/EllipticalArc2d/with2.svg)\n\n",
                "type": "{ centerPoint : Point2d, xDirection : Direction2d, xRadius : Float, yRadius : Float, startAngle : Float, sweptAngle : Float } -> EllipticalArc2d"
            },
            {
                "name": "xAxis",
                "comment": " ",
                "type": "EllipticalArc2d -> Axis2d"
            },
            {
                "name": "xDirection",
                "comment": " ",
                "type": "EllipticalArc2d -> Direction2d"
            },
            {
                "name": "xRadius",
                "comment": " ",
                "type": "EllipticalArc2d -> Float"
            },
            {
                "name": "yAxis",
                "comment": " ",
                "type": "EllipticalArc2d -> Axis2d"
            },
            {
                "name": "yDirection",
                "comment": " ",
                "type": "EllipticalArc2d -> Direction2d"
            },
            {
                "name": "yRadius",
                "comment": " ",
                "type": "EllipticalArc2d -> Float"
            }
        ],
        "binops": []
    },
    {
        "name": "OpenSolid.CubicSpline2d",
        "comment": " <img src=\"https://opensolid.github.io/images/geometry/icons/cubicSpline2d.svg\" alt=\"CubicSpline2d\" width=\"160\">\n\nA `CubicSpline2d` is a cubic [Bézier curve](https://en.wikipedia.org/wiki/B%C3%A9zier_curve)\nin 2D defined by four control points. This module contains functionality for\n\n  - Evaluating points and derivatives along a spline\n  - Scaling, rotating, translating or mirroring a spline\n  - Converting a spline between local and global coordinates in different\n    reference frames\n\n@docs CubicSpline2d\n\n\n# Constructors\n\n@docs fromControlPoints, hermite, fromQuadraticSpline\n\n\n# Properties\n\n@docs controlPoints, startPoint, endPoint, startDerivative, endDerivative\n\n\n# Evaluation\n\n@docs pointOn, derivative, evaluate\n\n\n# Transformations\n\n@docs reverse, scaleAbout, rotateAround, translateBy, mirrorAcross\n\n\n# Coordinate conversions\n\n@docs relativeTo, placeIn\n\n\n# Subdivision\n\n@docs bisect, splitAt\n\n\n# Arc length parameterization\n\n@docs ArcLengthParameterized, arcLengthParameterized, arcLength, pointAlong, tangentAlong, arcLengthToParameterValue, parameterValueToArcLength\n\n\n# Low level\n\nLow level functionality that you are unlikely to need to use directly.\n\n@docs derivativeMagnitude, maxSecondDerivativeMagnitude\n\n",
        "unions": [
            {
                "name": "ArcLengthParameterized",
                "comment": " A spline that has been parameterized by arc length.\n",
                "args": [],
                "cases": []
            }
        ],
        "aliases": [
            {
                "name": "CubicSpline2d",
                "comment": " ",
                "args": [],
                "type": "CubicSpline2d"
            }
        ],
        "values": [
            {
                "name": "arcLength",
                "comment": " Find the total arc length of a spline. This will be accurate to within the\ntolerance given when calling `arcLengthParameterized`.\n\n    arcLength : Float\n    arcLength =\n        CubicSpline2d.arcLength parameterizedSpline\n\n    arcLength\n    --> 7.0952\n\n",
                "type": "ArcLengthParameterized -> Float"
            },
            {
                "name": "arcLengthParameterized",
                "comment": " Build an arc length parameterization of the given spline, within\na given tolerance. Generally speaking, all operations on the resulting\n`ArcLengthParameterized` value will be accurate to within the given arc length\ntolerance.\n\n    tolerance =\n        1.0e-4\n\n    parameterizedSpline =\n        CubicSpline2d.arcLengthParameterized\n            tolerance\n            exampleSpline\n\n",
                "type": "Float -> CubicSpline2d -> ArcLengthParameterized"
            },
            {
                "name": "arcLengthToParameterValue",
                "comment": " Try to get the parameter value along a spline at a given arc length. If the\ngiven arc length is less than zero or greater than the arc length of the spline,\nreturns `Nothing`.\n\n    CubicSpline2d.arcLengthToParameterValue\n        parameterizedSpline\n        (arcLength / 4)\n    --> Just 0.2113\n\n",
                "type": "ArcLengthParameterized -> Float -> Maybe Float"
            },
            {
                "name": "bisect",
                "comment": " Split a spline into two roughly equal halves. Equivalent to `splitAt 0.5`.\n\n    CubicSpline2d.bisect exampleSpline\n    --> ( CubicSpline2d.fromControlPoints\n    -->     ( Point2d.fromCoordinates ( 1, 1 )\n    -->     , Point2d.fromCoordinates ( 2, 2.5 )\n    -->     , Point2d.fromCoordinates ( 3, 2.5 )\n    -->     , Point2d.fromCoordinates ( 4, 2.5 )\n    -->     )\n    --> , CubicSpline2d.fromControlPoints\n    -->     ( Point2d.fromCoordinates ( 4, 2.5 )\n    -->     , Point2d.fromCoordinates ( 5, 2.5 )\n    -->     , Point2d.fromCoordinates ( 6, 2.5 )\n    -->     , Point2d.fromCoordinates ( 7, 4 )\n    -->     )\n    --> )\n\n",
                "type": "CubicSpline2d -> ( CubicSpline2d, CubicSpline2d )"
            },
            {
                "name": "controlPoints",
                "comment": " Get the control points of a spline as a tuple.\n\n    ( p1, p2, p3, p4 ) =\n        CubicSpline2d.controlPoints exampleSpline\n\n\n    --> p1 = Point2d.fromCoordinates ( 1, 1 )\n    --> p2 = Point2d.fromCoordinates ( 3, 4 )\n    --> p3 = Point2d.fromCoordinates ( 5, 1 )\n    --> p4 = Point2d.fromCoordinates ( 7, 4 )\n\n",
                "type": "CubicSpline2d -> ( Point2d, Point2d, Point2d, Point2d )"
            },
            {
                "name": "derivative",
                "comment": " Get the deriative value at a point along a spline, based on a parameter that\nranges from 0 to 1. A parameter value of 0 corresponds to the start derivative\nof the spline and a value of 1 corresponds to the end derivative.\n\n    CubicSpline2d.derivative exampleSpline 0\n    --> Vector2d.fromComponents ( 6, 9 )\n\n    CubicSpline2d.derivative exampleSpline 0.5\n    --> Vector2d.fromComponents ( 6, 0 )\n\n    CubicSpline2d.derivative exampleSpline 1\n    --> Vector2d.fromComponents ( 6, 9 )\n\n",
                "type": "CubicSpline2d -> Float -> Vector2d"
            },
            {
                "name": "derivativeMagnitude",
                "comment": " Find the magnitude of the derivative to a spline at a particular parameter\nvalue;\n\n    CubicSpline2d.derivativeMagnitude spline t\n\nis equivalent to\n\n    Vector2d.length (CubicSpline2d.derivative spline t)\n\nbut more efficient since it avoids any intermediate `Vector2d` allocation.\n\n",
                "type": "CubicSpline2d -> Float -> Float"
            },
            {
                "name": "endDerivative",
                "comment": " Get the end derivative of a spline. This is equal to three times the vector\nfrom the spline's third control point to its fourth.\n\n    CubicSpline2d.endDerivative exampleSpline\n    --> Vector2d.fromComponents ( 6, 9 )\n\n",
                "type": "CubicSpline2d -> Vector2d"
            },
            {
                "name": "endPoint",
                "comment": " Get the end point of a spline. This is equal to the spline's last control\npoint.\n\n    CubicSpline2d.endPoint exampleSpline\n    --> Point2d.fromCoordinates ( 7, 4 )\n\n",
                "type": "CubicSpline2d -> Point2d"
            },
            {
                "name": "evaluate",
                "comment": " Evaluate a spline at a given parameter value, returning the point on the\nspline at that parameter value and the derivative with respect to that parameter\nvalue;\n\n    CubicSpline2d.evaluate spline t\n\nis equivalent to\n\n    ( CubicSpline2d.pointOn spline t\n    , CubicSpline2d.derivative spline t\n    )\n\nbut is more efficient.\n\n",
                "type": "CubicSpline2d -> Float -> ( Point2d, Vector2d )"
            },
            {
                "name": "fromControlPoints",
                "comment": " Construct a spline from its four control points:\n\n    exampleSpline =\n        CubicSpline2d.fromControlPoints\n            ( Point2d.fromCoordinates ( 1, 1 )\n            , Point2d.fromCoordinates ( 3, 4 )\n            , Point2d.fromCoordinates ( 5, 1 )\n            , Point2d.fromCoordinates ( 7, 4 )\n            )\n\n",
                "type": "( Point2d, Point2d, Point2d, Point2d ) -> CubicSpline2d"
            },
            {
                "name": "fromQuadraticSpline",
                "comment": " Convert a quadratic spline into the equivalent cubic spline (every quadratic\nspline can be represented exactly as a cubic spline).\n\n    quadraticSpline =\n        QuadraticSpline2d.fromControlPoints\n            ( Point2d.fromCoordinates ( 0, 0  )\n            , Point2d.fromCoordinates ( 3, 0 )\n            , Point2d.fromCoordinates ( 3, 3 )\n            )\n\n    CubicSpline2d.fromQuadraticSpline quadraticSpline\n    --> CubicSpline2d.fromControlPoints\n    -->     ( Point2d.fromCoordinates ( 0, 0 )\n    -->     , Point2d.fromCoordinates ( 2, 0 )\n    -->     , Point2d.fromCoordinates ( 3, 1 )\n    -->     , Point2d.fromCoordinates ( 3, 3 )\n    -->     )\n\n",
                "type": "QuadraticSpline2d -> CubicSpline2d"
            },
            {
                "name": "hermite",
                "comment": " Construct a spline in Hermite form, from the position and derivative values\nat its start and end points, like so:\n\n![Hermite cubic spline](https://opensolid.github.io/images/geometry/1.2/hermiteCubicSpline.svg)\n\nThe spline is based on a parameter that ranges from 0 to 1; as a result, in most\ncases the length of each derivative vector should be roughly equal to the length\nof the resulting spline.\n\n",
                "type": "( Point2d, Vector2d ) -> ( Point2d, Vector2d ) -> CubicSpline2d"
            },
            {
                "name": "maxSecondDerivativeMagnitude",
                "comment": " Find an upper bound on the magnitude of the second derivative of a spline.\n",
                "type": "CubicSpline2d -> Float"
            },
            {
                "name": "mirrorAcross",
                "comment": " Mirror a spline across an axis.\n\n    CubicSpline2d.mirrorAcross Axis2d.x exampleSpline\n    --> CubicSpline2d.fromControlPoints\n    -->     ( Point2d.fromCoordinates ( 1, -1 )\n    -->     , Point2d.fromCoordinates ( 3, -4 )\n    -->     , Point2d.fromCoordinates ( 5, -1 )\n    -->     , Point2d.fromCoordinates ( 7, -4 )\n    -->     )\n\n",
                "type": "Axis2d -> CubicSpline2d -> CubicSpline2d"
            },
            {
                "name": "parameterValueToArcLength",
                "comment": " Try to get the arc length along a spline at a given parameter value. If the\ngiven parameter value is less than zero or greater than one, returns `Nothing`.\n\n    CubicSpline2d.parameterValueToArcLength\n        parameterizedSpline\n        0.25\n    --> 2.0269\n\n",
                "type": "ArcLengthParameterized -> Float -> Maybe Float"
            },
            {
                "name": "placeIn",
                "comment": " Take a spline considered to be defined in local coordinates relative to a\ngiven reference frame, and return that spline expressed in global coordinates.\n\n    localFrame =\n        Frame2d.atPoint (Point2d.fromCoordinates ( 1, 2 ))\n\n    CubicSpline2d.placeIn localFrame exampleSpline\n    --> CubicSpline2d.fromControlPoints\n    -->     ( Point2d.fromCoordinates ( 2, 3 )\n    -->     , Point2d.fromCoordinates ( 4, 6 )\n    -->     , Point2d.fromCoordinates ( 6, 3 )\n    -->     , Point2d.fromCoordinates ( 8, 6 )\n    -->     )\n\n",
                "type": "Frame2d -> CubicSpline2d -> CubicSpline2d"
            },
            {
                "name": "pointAlong",
                "comment": " Try to get the point along a spline at a given arc length. For example, to\nget the point a quarter of the way along `exampleSpline`:\n\n    CubicSpline2d.pointAlong parameterizedSpline\n        (arcLength / 4)\n    --> Just (Point2d.fromCoordinates ( 2.2681, 2.2114 ))\n\nNote that this is not the same as evaulating at a parameter value of 1/4:\n\n    CubicSpline2d.pointOn exampleSpline 0.25\n    --> Point2d.fromCoordinates ( 2.5, 2.3125 )\n\nIf the given arc length is less than zero or greater than the arc length of the\nspline, `Nothing` is returned.\n\n",
                "type": "ArcLengthParameterized -> Float -> Maybe Point2d"
            },
            {
                "name": "pointOn",
                "comment": " Get a point along a spline, based on a parameter that ranges from 0 to 1. A\nparameter value of 0 corresponds to the start point of the spline and a value of\n1 corresponds to the end point.\n\n    CubicSpline2d.pointOn exampleSpline 0\n    --> Point2d.fromCoordinates ( 1, 1 )\n\n    CubicSpline2d.pointOn exampleSpline 0.5\n    --> Point2d.fromCoordinates ( 4, 2.5 )\n\n    CubicSpline2d.pointOn exampleSpline 1\n    --> Point2d.fromCoordinates ( 7, 4 )\n\n",
                "type": "CubicSpline2d -> Float -> Point2d"
            },
            {
                "name": "relativeTo",
                "comment": " Take a spline defined in global coordinates, and return it expressed in\nlocal coordinates relative to a given reference frame.\n\n    localFrame =\n        Frame2d.atPoint (Point2d.fromCoordinates ( 1, 2 ))\n\n    CubicSpline2d.relativeTo localFrame exampleSpline\n    --> CubicSpline2d.fromControlPoints\n    -->     ( Point2d.fromCoordinates ( 0, -1 )\n    -->     , Point2d.fromCoordinates ( 2, 2 )\n    -->     , Point2d.fromCoordinates ( 4, -1 )\n    -->     , Point2d.fromCoordinates ( 6, 2 )\n    -->     )\n\n",
                "type": "Frame2d -> CubicSpline2d -> CubicSpline2d"
            },
            {
                "name": "reverse",
                "comment": " Reverse a spline so that the start point becomes the end point, and vice\nversa.\n\n    CubicSpline2d.reverse exampleSpline\n    --> CubicSpline2d.fromControlPoints\n    -->     ( Point2d.fromCoordinates ( 7, 4 )\n    -->     , Point2d.fromCoordinates ( 5, 1 )\n    -->     , Point2d.fromCoordinates ( 3, 4 )\n    -->     , Point2d.fromCoordinates ( 1, 1 )\n    -->     )\n\n",
                "type": "CubicSpline2d -> CubicSpline2d"
            },
            {
                "name": "rotateAround",
                "comment": " Rotate a spline counterclockwise around a given center point by a given\nangle (in radians).\n\n    exampleSpline\n        |> CubicSpline2d.rotateAround Point2d.origin\n            (degrees 90)\n    --> CubicSpline2d.fromControlPoints\n    -->     ( Point2d.fromCoordinates ( -1, 1 )\n    -->     , Point2d.fromCoordinates ( -4, 3 )\n    -->     , Point2d.fromCoordinates ( -1, 5 )\n    -->     , Point2d.fromCoordinates ( -4, 7 )\n    -->     )\n\n",
                "type": "Point2d -> Float -> CubicSpline2d -> CubicSpline2d"
            },
            {
                "name": "scaleAbout",
                "comment": " Scale a spline about the given center point by the given scale.\n\n    CubicSpline2d.scaleAbout Point2d.origin 2 exampleSpline\n    --> CubicSpline2d.fromControlPoints\n    -->     ( Point2d.fromCoordinates ( 2, 2 )\n    -->     , Point2d.fromCoordinates ( 6, 8 )\n    -->     , Point2d.fromCoordinates ( 10, 2 )\n    -->     , Point2d.fromCoordinates ( 14, 8 )\n    -->     )\n\n",
                "type": "Point2d -> Float -> CubicSpline2d -> CubicSpline2d"
            },
            {
                "name": "splitAt",
                "comment": " Split a spline at a particular parameter value (in the range 0 to 1),\nresulting in two smaller splines.\n\n    CubicSpline2d.splitAt 0.75 exampleSpline\n    --> ( CubicSpline2d.fromControlPoints\n    -->     ( Point2d.fromCoordinates ( 1, 1 )\n    -->     , Point2d.fromCoordinates ( 2.5, 3.25 )\n    -->     , Point2d.fromCoordinates ( 4, 2.125 )\n    -->     , Point2d.fromCoordinates ( 5.5, 2.6875 )\n    -->     )\n    --> , CubicSpline2d.fromControlPoints\n    -->     ( Point2d.fromCoordinates ( 5.5, 2.6875 )\n    -->     , Point2d.fromCoordinates ( 6, 2.875 )\n    -->     , Point2d.fromCoordinates ( 6.5, 3.25 )\n    -->     , Point2d.fromCoordinates ( 7, 4 )\n    -->     )\n    --> )\n\n",
                "type": "Float -> CubicSpline2d -> ( CubicSpline2d, CubicSpline2d )"
            },
            {
                "name": "startDerivative",
                "comment": " Get the start derivative of a spline. This is equal to three times the\nvector from the spline's first control point to its second.\n\n    CubicSpline2d.startDerivative exampleSpline\n    --> Vector2d.fromComponents ( 6, 9 )\n\n",
                "type": "CubicSpline2d -> Vector2d"
            },
            {
                "name": "startPoint",
                "comment": " Get the start point of a spline. This is equal to the spline's first control\npoint.\n\n    CubicSpline2d.startPoint exampleSpline\n    --> Point2d.fromCoordinates ( 1, 1 )\n\n",
                "type": "CubicSpline2d -> Point2d"
            },
            {
                "name": "tangentAlong",
                "comment": " Try to get the tangent direction along a spline at a given arc length. To\nget the tangent direction a quarter of the way along `exampleSpline`:\n\n    CubicSpline2d.tangentAlong parameterizedSpline\n        (arcLength / 4)\n    --> Just (Direction2d.fromAngle (degrees 26.5611))\n\nIf the given arc length is less than zero or greater than the arc length of the\nspline (or if the derivative of the spline happens to be exactly zero at the\ngiven arc length), `Nothing` is returned.\n\n",
                "type": "ArcLengthParameterized -> Float -> Maybe Direction2d"
            },
            {
                "name": "translateBy",
                "comment": " Translate a spline by a given displacement.\n\n    displacement =\n        Vector2d.fromComponents ( 2, 3 )\n\n    CubicSpline2d.translateBy displacement exampleSpline\n    --> CubicSpline2d.fromControlPoints\n    -->     ( Point2d.fromCoordinates ( 3, 4 )\n    -->     , Point2d.fromCoordinates ( 5, 7 )\n    -->     , Point2d.fromCoordinates ( 7, 4 )\n    -->     , Point2d.fromCoordinates ( 9, 7 )\n    -->     )\n\n",
                "type": "Vector2d -> CubicSpline2d -> CubicSpline2d"
            }
        ],
        "binops": []
    },
    {
        "name": "OpenSolid.Plane3d",
        "comment": " <img src=\"https://opensolid.github.io/images/geometry/icons/plane3d.svg\" alt=\"Plane3d\" width=\"160\">\n\nA `Plane3d` is an infinite flat plane in 3D. It is defined by an origin point\nand normal direction and is useful for several operations including:\n\n  - Mirroring across the plane\n  - Projecting onto the plane\n  - Measuring distance from the plane\n\n@docs Plane3d\n\n\n# Constants\n\n@docs xy, yz, zx\n\n\n# Constructors\n\n@docs with, throughPoints\n\n\n# Properties\n\n@docs originPoint, normalDirection, normalAxis\n\n\n# Transformations\n\n@docs offsetBy, flip, rotateAround, translateBy, moveTo, mirrorAcross\n\n\n# Coordinate conversions\n\n@docs relativeTo, placeIn\n\n",
        "unions": [],
        "aliases": [
            {
                "name": "Plane3d",
                "comment": " ",
                "args": [],
                "type": "Plane3d"
            }
        ],
        "values": [
            {
                "name": "flip",
                "comment": " Reverse a plane's normal direction while leaving its origin point unchanged.\n\n    Plane3d.flip Plane3d.xy\n    --> Plane3d.with\n    -->     { originPoint = Point3d.origin\n    -->     , normalDirection = Direction3d.negativeZ\n    -->     }\n\n",
                "type": "Plane3d -> Plane3d"
            },
            {
                "name": "mirrorAcross",
                "comment": " Mirror one plane across another. The plane to mirror across is given first\nand the plane to mirror is given second.\n\n    plane =\n        Plane3d.with\n            { originPoint =\n                Point3d.fromCoordinates ( 1, 2, 3 )\n            , normalDirection = Direction3d.z\n            }\n\n    Plane3d.mirrorAcross Plane3d.xy plane\n    --> Plane3d.with\n    -->     { originPoint =\n    -->         Point3d.fromCoordinates ( 1, 2, -3 )\n    -->     , normalDirection = Direction3d.negativeZ\n    -->     }\n\n",
                "type": "Plane3d -> Plane3d -> Plane3d"
            },
            {
                "name": "moveTo",
                "comment": " Move a plane so that it has the given origin point but unchanged normal\ndirection.\n\n    newOrigin =\n        Point3d.fromCoordinates ( 1, 2, 3 )\n\n    Plane3d.moveTo newOrigin Plane3d.xy\n    --> Plane3d\n    -->     { originPoint = newOrigin\n    -->     , normalDirection = Direction3d.z\n    -->     }\n\n",
                "type": "Point3d -> Plane3d -> Plane3d"
            },
            {
                "name": "normalAxis",
                "comment": " Construct an axis from the origin point and normal direction of a plane.\n\n    Plane3d.normalAxis Plane3d.zx\n    --> Axis3d.y\n\n",
                "type": "Plane3d -> Axis3d"
            },
            {
                "name": "normalDirection",
                "comment": " Get the normal direction of a plane.\n\n    Plane3d.normalDirection Plane3d.xy\n    --> Direction3d.z\n\n",
                "type": "Plane3d -> Direction3d"
            },
            {
                "name": "offsetBy",
                "comment": " Shift a plane in its own normal direction by the given (signed) distance.\n\n    Plane3d.offsetBy 1.0 Plane3d.zx\n    --> Plane3d.with\n    -->     { originPoint =\n    -->         Point3d.fromCoordinates ( 0, 1, 0 )\n    -->     , normalDirection = Direction3d.y\n    -->     }\n\n    Plane3d.offsetBy -2.0 Plane3d.xy\n    --> Plane3d.with\n    -->     { originPoint =\n    -->         Point3d.fromCoordinates ( 0, 0, -2 )\n    -->     , normalDirection = Direction3d.z\n    -->     }\n\n",
                "type": "Float -> Plane3d -> Plane3d"
            },
            {
                "name": "originPoint",
                "comment": " Get the origin point of a plane.\n\n    Plane3d.originPoint Plane3d.xy\n    --> Point3d.origin\n\n",
                "type": "Plane3d -> Point3d"
            },
            {
                "name": "placeIn",
                "comment": " Take a plane defined in local coordinates relative to a given reference\nframe, and return that plane expressed in global coordinates.\n\n    referenceFrame =\n        Frame3d.atPoint\n            (Point3d.fromCoordinates ( 1, 1, 1 ))\n\n    plane =\n        Plane3d.with\n            { originPoint =\n                Point3d.fromCoordinates ( 1, 2, 3 )\n            , normalDirection = Direction3d.z\n            }\n\n    Plane3d.placeIn referenceFrame plane\n    --> Plane3d.with\n    -->     { originPoint =\n    -->         Point3d.fromCoordinates ( 2, 3, 4 )\n    -->     , normalDirection = Direction3d.z\n    -->     }\n\n",
                "type": "Frame3d -> Plane3d -> Plane3d"
            },
            {
                "name": "relativeTo",
                "comment": " Take a plane defined in global coordinates, and return it expressed in local\ncoordinates relative to a given reference frame.\n\n    referenceFrame =\n        Frame3d.atPoint\n            (Point3d.fromCoordinates ( 1, 1, 1 ))\n\n    plane =\n        Plane3d.with\n            { originPoint =\n                Point3d.fromCoordinates ( 0, 0, 2 )\n            , normalDirection = Direction3d.z\n            }\n\n    Plane3d.relativeTo referenceFrame plane\n    --> Plane3d.with\n    -->     { originPoint =\n    -->         Point3d.fromCoordinates ( -1, -1, 1 )\n    -->     , normalDirection = Direction3d.z\n    -->     }\n\n",
                "type": "Frame3d -> Plane3d -> Plane3d"
            },
            {
                "name": "rotateAround",
                "comment": " Rotate a plane around an axis by a given angle.\n\n    Plane3d.rotateAround Axis3d.y (degrees 90) Plane3d.xy\n    --> Plane3d.yz\n\n",
                "type": "Axis3d -> Float -> Plane3d -> Plane3d"
            },
            {
                "name": "throughPoints",
                "comment": " Attempt to construct a plane passing through the three given points. The\norigin point of the resulting plane will be equal to the first given point, and\nthe normal direction will be such that the three given points are in\ncounterclockwise order around it according to the right-hand rule. If the three\ngiven points are collinear, returns `Nothing`.\n\n    Plane3d.throughPoints\n        ( Point3d.fromCoordinates ( 2, 0, 0 )\n        , Point3d.fromCoordinates ( 3, 0, 0 )\n        , Point3d.fromCoordinates ( 4, 1, 1 )\n        )\n    --> Just\n    -->     (Plane3d.with\n    -->         { originPoint =\n    -->             Point3d.fromCoordinates ( 2, 0, 0 )\n    -->         , normalDirection =\n    -->             Direction3d.with\n    -->                 { azimuth = degrees -90\n    -->                 , elevation = degrees 45\n    -->                 }\n    -->         }\n    -->     )\n\n    Plane3d.throughPoints\n        ( Point3d.fromCoordinates ( 2, 0, 0 )\n        , Point3d.fromCoordinates ( 3, 0, 0 )\n        , Point3d.fromCoordinates ( 4, 0, 0 )\n        )\n    --> Nothing\n\n",
                "type": "( Point3d, Point3d, Point3d ) -> Maybe Plane3d"
            },
            {
                "name": "translateBy",
                "comment": " Translate a plane by a given displacement. Applies the given displacement to\nthe plane's origin point and leaves its normal direction unchanged.\n\n    plane =\n        Plane3d.with\n            { originPoint =\n                Point3d.fromCoordinates ( 1, 1, 1 )\n            , normalDirection = Direction3d.z\n            }\n\n    displacement =\n        Vector3d.fromComponents ( 1, 2, 3 )\n\n    Plane3d.translateBy displacement plane\n    --> Plane3d\n    -->     { originPoint =\n    -->         Point3d.fromCoordinates ( 2, 3, 4 )\n    -->     , normalDirection = Direction3d.z\n    -->     }\n\n",
                "type": "Vector3d -> Plane3d -> Plane3d"
            },
            {
                "name": "with",
                "comment": " Construct a plane from its origin point and normal direction:\n\n    plane =\n        Plane3d.with\n            { originPoint =\n                Point3d.fromCoordinates ( 2, 1, 3 )\n            , normalDirection = Direction3d.y\n            }\n\n",
                "type": "{ originPoint : Point3d, normalDirection : Direction3d } -> Plane3d"
            },
            {
                "name": "xy",
                "comment": " The global XY plane, centered at the origin with a normal in the positive Z\ndirection.\n\n    Plane3d.xy\n    --> Plane3d.with\n    -->     { originPoint = Point3d.origin\n    -->     , normalDirection = Direction3d.z\n    -->     }\n\n",
                "type": "Plane3d"
            },
            {
                "name": "yz",
                "comment": " The global YZ plane, centered at the origin with a normal in the positive X\ndirection.\n\n    Plane3d.yz\n    --> Plane3d.with\n    -->     { originPoint = Point3d.origin\n    -->     , normalDirection = Direction3d.x\n    -->     }\n\n",
                "type": "Plane3d"
            },
            {
                "name": "zx",
                "comment": " The global ZX plane, centered at the origin with a normal in the positive Y\ndirection.\n\n    Plane3d.zx\n    --> Plane3d.with\n    -->     { originPoint = Point3d.origin\n    -->     , normalDirection = Direction3d.y\n    -->     }\n\n",
                "type": "Plane3d"
            }
        ],
        "binops": []
    },
    {
        "name": "OpenSolid.LineSegment2d",
        "comment": " <img src=\"https://opensolid.github.io/images/geometry/icons/lineSegment2d.svg\" alt=\"LineSegment2d\" width=\"160\">\n\nA `LineSegment2d` is a line between two points in 2D. This module contains\nfunctionality such as:\n\n  - Interpolating within a line segment or measuring its length\n  - Scaling, rotating, translating, mirroring or projecting a line segment\n  - Converting a line segment between local and global coordinates in different\n    reference frames\n\n@docs LineSegment2d\n\n\n# Constructors\n\n@docs fromEndpoints, from, along\n\n\n# Properties\n\n@docs startPoint, endPoint, endpoints, midpoint, length, squaredLength, direction, normalDirection, vector, boundingBox\n\n\n# Interpolation\n\n@docs interpolate\n\n\n# Intersection\n\n@docs intersectionPoint\n\n\n# Transformations\n\nTransforming a line segment is equivalent to transforming its start and end\npoints and forming a new line segment between the resulting points.\n\n@docs reverse, scaleAbout, rotateAround, translateBy, mirrorAcross, projectOnto, mapEndpoints\n\n\n# Coordinate conversions\n\nFunctions for transforming line segments between local and global coordinates in\ndifferent coordinate frames.\n\n@docs relativeTo, placeIn\n\n",
        "unions": [],
        "aliases": [
            {
                "name": "LineSegment2d",
                "comment": " ",
                "args": [],
                "type": "LineSegment2d"
            }
        ],
        "values": [
            {
                "name": "along",
                "comment": " Construct a line segment lying on the given axis, with its endpoints at the\ngiven distances from the axis' origin point.\n\n    LineSegment2d.along Axis2d.x 3 5\n    --> LineSegment2d.fromEndpoints\n    -->     ( Point2d.fromCoordinates ( 3, 0 )\n    -->     , Point2d.fromCoordinates ( 5, 0 )\n    -->     )\n\n    LineSegment2d.along Axis2d.y 2 -4\n    --> LineSegment2d.fromEndpoints\n    -->     ( Point2d.fromCoordinates ( 0, 2 )\n    -->     , Point2d.fromCoordinates ( 0, -4 )\n    -->     )\n\n",
                "type": "Axis2d -> Float -> Float -> LineSegment2d"
            },
            {
                "name": "boundingBox",
                "comment": " Get the minimal bounding box containing a given line segment.\n\n    LineSegment2d.boundingBox exampleLineSegment\n    --> BoundingBox2d.with\n    -->     { minX = 1\n    -->     , maxX = 3\n    -->     , minY = 2\n    -->     , maxY = 4\n    -->     }\n\n",
                "type": "LineSegment2d -> BoundingBox2d"
            },
            {
                "name": "direction",
                "comment": " Get the direction from a line segment's start point to its end point. If the\nline segment has zero length (the start and end points are the same), returns\n`Nothing`.\n\n    LineSegment2d.direction exampleLineSegment\n    --> Just (Direction2d.fromAngle (degrees 45))\n\n",
                "type": "LineSegment2d -> Maybe Direction2d"
            },
            {
                "name": "endPoint",
                "comment": " Get the end point of a line segment.\n\n    LineSegment2d.endPoint exampleLineSegment\n    --> Point2d.fromCoordinates ( 3, 4 )\n\n",
                "type": "LineSegment2d -> Point2d"
            },
            {
                "name": "endpoints",
                "comment": " Get the endpoints of a line segment as a tuple.\n\n    ( p1, p2 ) =\n        LineSegment2d.endpoints lineSegment\n\n",
                "type": "LineSegment2d -> ( Point2d, Point2d )"
            },
            {
                "name": "from",
                "comment": " Construct a line segment from the first point to the second;\n\n    LineSegment2d.from firstPoint secondPoint\n\nis equivalent to\n\n    LineSegment2d.fromEndpoints ( firstPoint, secondPoint )\n\n",
                "type": "Point2d -> Point2d -> LineSegment2d"
            },
            {
                "name": "fromEndpoints",
                "comment": " Construct a line segment from its two endpoints:\n\n    exampleLineSegment =\n        LineSegment2d.fromEndpoints\n            ( Point2d.fromCoordinates ( 1, 2 )\n            , Point2d.fromCoordinates ( 3, 4 )\n            )\n\n",
                "type": "( Point2d, Point2d ) -> LineSegment2d"
            },
            {
                "name": "interpolate",
                "comment": " Interpolate a line segment between its start and end points; a value of 0.0\ncorresponds to the start point of the line segment, a value of 0.5 corresponds\nto its midpoint and a value of 1.0 corresponds to its end point. Values less\nthan 0.0 or greater than 1.0 can be used to extrapolate.\n\n    LineSegment2d.interpolate exampleLineSegment 0.25\n    --> Point2d.fromCoordinates ( 1.5, 2.5 )\n\n    LineSegment2d.interpolate exampleLineSegment 1.5\n    --> Point2d.fromCoordinates ( 4, 5 )\n\n",
                "type": "LineSegment2d -> Float -> Point2d"
            },
            {
                "name": "intersectionPoint",
                "comment": " Attempt to find the unique intersection point of two line segments. If there\nis no such point (the two line segments do not touch, or they overlap), returns\n`Nothing`.\n\n    -- 4 corners of a square\n    ( a, b, c, d ) =\n        ( Point2d.fromCoordinates ( 0, 0 )\n        , Point2d.fromCoordinates ( 1, 0 )\n        , Point2d.fromCoordinates ( 1, 1 )\n        , Point2d.fromCoordinates ( 0, 1 )\n        )\n\n    -- definition of some segments with those points\n    ab =\n        LineSegment2d.from a b\n    ...\n\n    -- searching for intersections\n\n    LineSegment2d.intersectionPoint ab bc\n    --> Just (Point2d.fromCoordinates ( 1, 0 ))\n    -- corner point b\n\n    LineSegment2d.intersectionPoint ac bd\n    --> Just (Point2d.fromCoordinates ( 0.5, 0.5 ))\n    -- diagonal crossing at square center\n\n    LineSegment2d.intersectionPoint ab cd\n    --> Nothing -- parallel lines\n\n    LineSegment2d.intersectionPoint ab ab\n    --> Nothing -- collinear lines\n\nNote that if the endpoint of one line segment lies on the other line segment,\nnumerical roundoff means that the intersection may or may not be found. If two\nsegments have a shared endpoint (the two segments meet in something like a 'V',\nwhere the end point of one segment is the start point of the next), that point\nis guaranteed to be returned as the intersection point, but if two segments meet\nin a 'T' shape the intersection point may or may not be found.\n\n",
                "type": "LineSegment2d -> LineSegment2d -> Maybe Point2d"
            },
            {
                "name": "length",
                "comment": " Get the length of a line segment.\n\n    LineSegment2d.length exampleLineSegment\n    --> 2.8284\n\n",
                "type": "LineSegment2d -> Float"
            },
            {
                "name": "mapEndpoints",
                "comment": " Transform the start and end points of a line segment by a given function\nand create a new line segment from the resulting points. Most other\ntransformation functions can be defined in terms of `mapEndpoints`; for example,\n\n    LineSegment2d.projectOnto axis\n\nis equivalent to\n\n    LineSegment2d.mapEndpoints (Point2d.projectOnto axis)\n\n",
                "type": "(Point2d -> Point2d) -> LineSegment2d -> LineSegment2d"
            },
            {
                "name": "midpoint",
                "comment": " Get the midpoint of a line segment.\n\n    LineSegment2d.midpoint exampleLineSegment\n    --> Point2d.fromCoordinates ( 2, 3 )\n\n",
                "type": "LineSegment2d -> Point2d"
            },
            {
                "name": "mirrorAcross",
                "comment": " Mirror a line segment across an axis.\n\n    LineSegment2d.mirrorAcross Axis2d.y exampleLineSegment\n    --> LineSegment2d.fromEndpoints\n    -->     ( Point2d.fromCoordinates ( -1, 2 )\n    -->     , Point2d.fromCoordinates ( -3, 4 )\n    -->     )\n\nNote that the endpoints of a mirrored segment are equal to the mirrored\nendpoints of the original segment, but as a result the normal direction of a\nmirrored segment is the _opposite_ of the mirrored normal direction of the\noriginal segment (since the normal direction is always considered to be 'to the\nleft' of the line segment).\n\n",
                "type": "Axis2d -> LineSegment2d -> LineSegment2d"
            },
            {
                "name": "normalDirection",
                "comment": " Get the direction perpendicular to a line segment, pointing to the left. If\nthe line segment has zero length, returns `Nothing`.\n\n    LineSegment2d.normalDirection exampleLineSegment\n    --> Just (Direction2d.fromAngle (degrees 135))\n\n",
                "type": "LineSegment2d -> Maybe Direction2d"
            },
            {
                "name": "placeIn",
                "comment": " Take a line segment considered to be defined in local coordinates relative\nto a given reference frame, and return that line segment expressed in global\ncoordinates.\n\n    localFrame =\n        Frame2d.atPoint (Point2d.fromCoordinates ( 1, 2 ))\n\n    LineSegment2d.placeIn localFrame exampleLineSegment\n    --> LineSegment2d.fromEndpoints\n    -->     ( Point2d.fromCoordinates ( 2, 4 )\n    -->     , Point2d.fromCoordinates ( 4, 6 )\n    -->     )\n\n",
                "type": "Frame2d -> LineSegment2d -> LineSegment2d"
            },
            {
                "name": "projectOnto",
                "comment": " Project a line segment onto an axis.\n\n    LineSegment2d.projectOnto Axis2d.x exampleLineSegment\n    --> LineSegment2d.fromEndpoints\n    -->     ( Point2d.fromCoordinates ( 1, 0 )\n    -->     , Point2d.fromCoordinates ( 3, 0 )\n    -->     )\n\n    LineSegment2d.projectOnto Axis2d.y exampleLineSegment\n    --> LineSegment2d.fromEndpoints\n    -->     ( Point2d.fromCoordinates ( 0, 2 )\n    -->     , Point2d.fromCoordinates ( 0, 4 )\n    -->     )\n\n",
                "type": "Axis2d -> LineSegment2d -> LineSegment2d"
            },
            {
                "name": "relativeTo",
                "comment": " Take a line segment defined in global coordinates, and return it expressed\nin local coordinates relative to a given reference frame.\n\n    localFrame =\n        Frame2d.atPoint (Point2d.fromCoordinates ( 1, 2 ))\n\n    LineSegment2d.relativeTo localFrame exampleLineSegment\n    --> LineSegment2d.fromEndpoints\n    -->     ( Point2d.fromCoordinates ( 0, 0 )\n    -->     , Point2d.fromCoordinates ( 2, 2 )\n    -->     )\n\n",
                "type": "Frame2d -> LineSegment2d -> LineSegment2d"
            },
            {
                "name": "reverse",
                "comment": " Reverse a line segment, swapping its start and end points.\n\n    LineSegment2d.reverse exampleLineSegment\n    --> LineSegment2d.fromEndpoints\n    -->     ( Point2d.fromCoordinates ( 3, 4 )\n    -->     , Point2d.fromCoordinates ( 1, 2 )\n    -->     )\n\n",
                "type": "LineSegment2d -> LineSegment2d"
            },
            {
                "name": "rotateAround",
                "comment": " Rotate a line segment counterclockwise around a given center point by a\ngiven angle (in radians).\n\n    exampleLineSegment\n        |> LineSegment2d.rotateAround Point2d.origin\n            (degrees 90)\n    --> LineSegment2d.fromEndpoints\n    -->     ( Point2d.fromCoordinates ( -2, 1 )\n    -->     , Point2d.fromCoordinates ( -4, 3 )\n    -->     )\n\n",
                "type": "Point2d -> Float -> LineSegment2d -> LineSegment2d"
            },
            {
                "name": "scaleAbout",
                "comment": " Scale a line segment about the given center point by the given scale.\n\n    point =\n        Point2d.fromCoordinates ( 1, 1 )\n\n    LineSegment2d.scaleAbout point 2 exampleLineSegment\n    --> LineSegment2d.fromEndpoints\n    -->     ( Point2d.fromCoordinates ( 1, 3 )\n    -->     , Point2d.fromCoordinates ( 5, 7 )\n    -->     )\n\n",
                "type": "Point2d -> Float -> LineSegment2d -> LineSegment2d"
            },
            {
                "name": "squaredLength",
                "comment": " Get the squared length of a line segment. Slightly more efficient than\n`length` since it avoids a square root.\n\n    LineSegment2d.squaredLength exampleLineSegment\n    --> 8\n\n",
                "type": "LineSegment2d -> Float"
            },
            {
                "name": "startPoint",
                "comment": " Get the start point of a line segment.\n\n    LineSegment2d.startPoint exampleLineSegment\n    --> Point2d.fromCoordinates ( 1, 2 )\n\n",
                "type": "LineSegment2d -> Point2d"
            },
            {
                "name": "translateBy",
                "comment": " Translate a line segment by a given displacement.\n\n    displacement =\n        Vector2d.fromComponents ( 1, 2 )\n\n    exampleLineSegment\n        |> LineSegment2d.translateBy displacement\n    --> LineSegment2d.fromEndpoints\n    -->     ( Point2d.fromCoordinates ( 2, 4 )\n    -->     , Point2d.fromCoordinates ( 4, 6 )\n    -->     )\n\n",
                "type": "Vector2d -> LineSegment2d -> LineSegment2d"
            },
            {
                "name": "vector",
                "comment": " Get the vector from a given line segment's start point to its end point.\n\n    LineSegment2d.vector exampleLineSegment\n    --> Vector2d.fromComponents ( 2, 2 )\n\n",
                "type": "LineSegment2d -> Vector2d"
            }
        ],
        "binops": []
    },
    {
        "name": "OpenSolid.Ellipse2d",
        "comment": " <img src=\"https://opensolid.github.io/images/geometry/icons/ellipse2d.svg\" alt=\"Ellipse2d\" width=\"160\">\n\nAn [ellipse](https://en.wikipedia.org/wiki/Ellipse) is defined by a center\npoint, X and Y radius, and X and Y axes (which will always be perpendicular to\neach other). Ellipses are symmetric about their X and Y axes. This module\nincludes functionality for\n\n  - Constructing ellipses\n  - Scaling, rotating and translating ellipses\n  - Converting ellipses between different coordinate systems\n\n@docs Ellipse2d\n\n\n# Constructors\n\n@docs with\n\n\n# Properties\n\n@docs centerPoint, xAxis, yAxis, xDirection, yDirection, axes, xRadius, yRadius, area\n\n\n# Transformations\n\n@docs scaleAbout, rotateAround, translateBy, mirrorAcross\n\n\n# Coordinate conversions\n\n@docs relativeTo, placeIn\n\n",
        "unions": [],
        "aliases": [
            {
                "name": "Ellipse2d",
                "comment": " An ellipse in 2D.\n",
                "args": [],
                "type": "Ellipse2d"
            }
        ],
        "values": [
            {
                "name": "area",
                "comment": " Get the area of an ellipse.\n\n    Ellipse2d.area exampleEllipse\n    --> 47.1239\n\n",
                "type": "Ellipse2d -> Float"
            },
            {
                "name": "axes",
                "comment": " Get the X and Y axes of an ellipse as a `Frame2d`.\n\n    Ellipse2d.axes exampleEllipse\n    --> Frame2d.with\n    -->     { originPoint =\n    -->         Point2d.fromCoordinates ( 10, 10 )\n    -->     , xDirection =\n    -->         Direction2d.fromAngle (degrees 30)\n    -->     }\n\n",
                "type": "Ellipse2d -> Frame2d"
            },
            {
                "name": "centerPoint",
                "comment": " Get the center point of an ellipse.\n\n    Ellipse2d.centerPoint exampleEllipse\n    --> Point2d.fromCoordinates ( 10, 10 )\n\n",
                "type": "Ellipse2d -> Point2d"
            },
            {
                "name": "mirrorAcross",
                "comment": " Mirror an ellipse across a given axis.\n\n    mirroredEllipse =\n        Ellipse2d.mirrorAcross Axis2d.x exampleEllipse\n\n    Ellipse2d.centerPoint mirroredEllipse\n    --> Point2d.fromCoordinates ( 10, -10 )\n\n    Ellipse2d.xDirection mirroredEllipse\n    --> Direction2d.fromAngle (degrees -30)\n\n    Ellipse2d.yDirection mirroredEllipse\n    --> Direction2d.fromAngle (degrees -120)\n\nNote that if the axes of the original ellipse form a [right-handed](https://en.wikipedia.org/wiki/Cartesian_coordinate_system#Orientation_and_handedness)\nframe, then the axes of the mirrored ellipse will form a left-handed frame (and\nvice versa).\n\n",
                "type": "Axis2d -> Ellipse2d -> Ellipse2d"
            },
            {
                "name": "placeIn",
                "comment": " Take an ellipse considered to be defined in local coordinates relative to a\ngiven reference frame, and return that circle expressed in global coordinates.\n\n    localFrame =\n        Frame2d.atPoint (Point2d.fromCoordinates (15, 5))\n\n    Ellipse2d.placeIn localFrame exampleEllipse\n    --> Ellipse2d.with\n    -->     { centerPoint =\n    -->         Point2d.fromCoordinates ( 25, 15 )\n    -->     , xDirection =\n    -->         Direction2d.fromAngle (degrees 30)\n    -->     , xRadius = 5\n    -->     , yRadius = 3\n    -->     }\n\n",
                "type": "Frame2d -> Ellipse2d -> Ellipse2d"
            },
            {
                "name": "relativeTo",
                "comment": " Take an ellipse defined in global coordinates, and return it expressed in\nlocal coordinates relative to a given reference frame.\n\n    localFrame =\n        Frame2d.atPoint (Point2d.fromCoordinates (15, 5))\n\n    Ellipse2d.relativeTo localFrame exampleEllipse\n    --> Ellipse2d.with\n    -->     { centerPoint =\n    -->         Point2d.fromCoordinates ( -5, 5 )\n    -->     , xDirection =\n    -->         Direction2d.fromAngle (degrees 30)\n    -->     , xRadius = 5\n    -->     , yRadius = 3\n    -->     }\n\n",
                "type": "Frame2d -> Ellipse2d -> Ellipse2d"
            },
            {
                "name": "rotateAround",
                "comment": " Rotate an ellipse around a given point by a given angle (in radians).\n\n    exampleEllipse\n        |> Ellipse2d.rotateAround Point2d.origin\n            (degrees 45)\n    --> Ellipse2d.with\n    -->     { centerPoint =\n    -->         Point2d.fromCoordinates ( 0, 14.142 )\n    -->     , xDirection =\n    -->         Direction2d.fromAngle (degrees 75)\n    -->     , xRadius = 5\n    -->     , yRadius = 3\n    -->     }\n\n",
                "type": "Point2d -> Float -> Ellipse2d -> Ellipse2d"
            },
            {
                "name": "scaleAbout",
                "comment": " Scale an ellipse about a given point by a given scale.\n\n    exampleEllipse\n        |> Ellipse2d.scaleAbout Point2d.origin 3\n    --> Ellipse2d.with\n    -->     { centerPoint =\n    -->         Point2d.fromCoordinates ( 30, 30 )\n    -->     , xDirection =\n    -->         Direction2d.fromAngle (degrees 30)\n    -->     , xRadius = 15\n    -->     , yRadius = 9\n    -->     }\n\n",
                "type": "Point2d -> Float -> Ellipse2d -> Ellipse2d"
            },
            {
                "name": "translateBy",
                "comment": " Translate an ellipse by a given displacement.\n\n    exampleEllipse\n        |> Ellipse2d.translateBy\n            (Vector2d.fromComponents ( 5, 10 ))\n    --> Ellipse2d.with\n    -->     { centerPoint =\n    -->         Point2d.fromCoordinates ( 15, 20 )\n    -->     , xDirection =\n    -->         Direction2d.fromAngle (degrees 30)\n    -->     , xRadius = 5\n    -->     , yRadius = 3\n    -->     }\n\n",
                "type": "Vector2d -> Ellipse2d -> Ellipse2d"
            },
            {
                "name": "with",
                "comment": " Construct an ellipse from its center point, X direction, and X and Y radii.\nNegative radii will be interpreted as positive (the absolute value will be\nused).\n\n    exampleEllipse =\n        Ellipse2d.with\n            { centerPoint =\n                Point2d.fromCoordinates ( 10, 10 )\n            , xDirection =\n                Direction2d.fromAngle (degrees 30)\n            , xRadius = 5\n            , yRadius = 3\n            }\n\n",
                "type": "{ centerPoint : Point2d, xDirection : Direction2d, xRadius : Float, yRadius : Float } -> Ellipse2d"
            },
            {
                "name": "xAxis",
                "comment": " Get the X axis of an ellipse.\n\n    Ellipse2d.xAxis exampleEllipse\n    --> Axis2d.with\n    -->     { originPoint =\n    -->          Point2d.fromCoordinates ( 10, 10 )\n    -->      , direction =\n    -->         Direction2d.fromAngle (degrees 30)\n    -->     }\n\n",
                "type": "Ellipse2d -> Axis2d"
            },
            {
                "name": "xDirection",
                "comment": " Get the direction of the ellipse's X axis.\n\n    Ellipse2d.xDirection exampleEllipse\n    --> Direction2d.fromAngle (degrees 30)\n\n",
                "type": "Ellipse2d -> Direction2d"
            },
            {
                "name": "xRadius",
                "comment": " Get the radius of an ellipse along its X axis. This may be either the\nminimum or maximum radius.\n\n    Ellipse2d.xRadius exampleEllipse\n    --> 5\n\n",
                "type": "Ellipse2d -> Float"
            },
            {
                "name": "yAxis",
                "comment": " Get the Y axis of an ellipse.\n\n    Ellipse2d.yAxis exampleEllipse\n    --> Axis2d.with\n    -->     { originPoint =\n    -->          Point2d.fromCoordinates ( 10, 10 )\n    -->      , direction =\n    -->         Direction2d.fromAngle (degrees 120)\n    -->     }\n\n",
                "type": "Ellipse2d -> Axis2d"
            },
            {
                "name": "yDirection",
                "comment": " Get the direction of an ellipse's Y axis.\n\n    Ellipse2d.yDirection exampleEllipse\n    --> Direction2d.fromAngle (degrees 120)\n\n",
                "type": "Ellipse2d -> Direction2d"
            },
            {
                "name": "yRadius",
                "comment": " Get the radius of an ellipse along its Y axis. This may be either the\nminimum or maximum radius.\n\n    Ellipse2d.yRadius exampleEllipse\n    --> 3\n\n",
                "type": "Ellipse2d -> Float"
            }
        ],
        "binops": []
    },
    {
        "name": "OpenSolid.QuadraticSpline2d",
        "comment": " <img src=\"https://opensolid.github.io/images/geometry/icons/quadraticSpline2d.svg\" alt=\"QuadraticSpline2d\" width=\"160\">\n\nA `QuadraticSpline2d` is a quadratic [Bézier curve](https://en.wikipedia.org/wiki/B%C3%A9zier_curve)\nin 2D defined by three control points. This module contains functionality for\n\n  - Evaluating points and derivatives along a spline\n  - Scaling, rotating, translating or mirroring a spline\n  - Converting a spline between local and global coordinates in different\n    reference frames\n\n@docs QuadraticSpline2d\n\n\n# Constructors\n\n@docs fromControlPoints\n\n\n# Properties\n\n@docs controlPoints, startPoint, endPoint, startDerivative, endDerivative\n\n\n# Evaluation\n\n@docs pointOn, derivative, evaluate\n\n\n# Transformations\n\n@docs reverse, scaleAbout, rotateAround, translateBy, mirrorAcross\n\n\n# Coordinate conversions\n\n@docs relativeTo, placeIn\n\n\n# Subdivision\n\n@docs bisect, splitAt\n\n\n# Arc length parameterization\n\n@docs ArcLengthParameterized, arcLengthParameterized, arcLength, pointAlong, tangentAlong, arcLengthToParameterValue, parameterValueToArcLength\n\n\n# Low level\n\nLow level functionality that you are unlikely to need to use directly.\n\n@docs derivativeMagnitude, secondDerivative\n\n",
        "unions": [
            {
                "name": "ArcLengthParameterized",
                "comment": " A spline that has been parameterized by arc length.\n",
                "args": [],
                "cases": []
            }
        ],
        "aliases": [
            {
                "name": "QuadraticSpline2d",
                "comment": " ",
                "args": [],
                "type": "QuadraticSpline2d"
            }
        ],
        "values": [
            {
                "name": "arcLength",
                "comment": " Find the total arc length of a spline. This will be accurate to within the\ntolerance given when calling `arcLengthParameterized`.\n\n    arcLength : Float\n    arcLength =\n        QuadraticSpline2d.arcLength parameterizedSpline\n\n    arcLength\n    --> 5.1986\n\n",
                "type": "ArcLengthParameterized -> Float"
            },
            {
                "name": "arcLengthParameterized",
                "comment": " Build an arc length parameterization of the given spline, within\na given tolerance. Generally speaking, all operations on the resulting\n`ArcLengthParameterized` value will be accurate to within the given arc length\ntolerance.\n\n    tolerance =\n        1.0e-4\n\n    parameterizedSpline =\n        QuadraticSpline2d.arcLengthParameterized\n            tolerance\n            exampleSpline\n\n",
                "type": "Float -> QuadraticSpline2d -> ArcLengthParameterized"
            },
            {
                "name": "arcLengthToParameterValue",
                "comment": " Try to get the parameter value along a spline at a given arc length. If the\ngiven arc length is less than zero or greater than the arc length of the spline,\nreturns `Nothing`.\n\n    QuadraticSpline2d.arcLengthToParameterValue\n        parameterizedSpline\n        (arcLength / 4)\n    --> Just 0.2088\n\n",
                "type": "ArcLengthParameterized -> Float -> Maybe Float"
            },
            {
                "name": "bisect",
                "comment": " Split a spline into two roughly equal halves. Equivalent to `splitAt 0.5`.\n\n    QuadraticSpline2d.bisect exampleSpline\n    --> ( QuadraticSpline2d.fromControlPoints\n    -->     ( Point2d.fromCoordinates ( 1, 1 )\n    -->     , Point2d.fromCoordinates ( 2, 2.5 )\n    -->     , Point2d.fromCoordinates ( 3, 2.5 )\n    -->     )\n    --> , QuadraticSpline2d.fromControlPoints\n    -->     ( Point2d.fromCoordinates ( 3, 2.5 )\n    -->     , Point2d.fromCoordinates ( 4, 2.5 )\n    -->     , Point2d.fromCoordinates ( 5, 1 )\n    -->     )\n    --> )\n\n",
                "type": "QuadraticSpline2d -> ( QuadraticSpline2d, QuadraticSpline2d )"
            },
            {
                "name": "controlPoints",
                "comment": " Get the control points of a spline as a tuple.\n\n    ( p1, p2, p3 ) =\n        QuadraticSpline2d.controlPoints exampleSpline\n\n\n    --> p1 = Point2d.fromCoordinates ( 1, 1 )\n    --> p2 = Point2d.fromCoordinates ( 3, 4 )\n    --> p3 = Point2d.fromCoordinates ( 5, 1 )\n\n",
                "type": "QuadraticSpline2d -> ( Point2d, Point2d, Point2d )"
            },
            {
                "name": "derivative",
                "comment": " Get the deriative value at a point along a spline, based on a parameter that\nranges from 0 to 1. A parameter value of 0 corresponds to the start derivative\nof the spline and a value of 1 corresponds to the end derivative.\n\n    QuadraticSpline2d.derivative exampleSpline 0\n    --> Vector2d.fromComponents ( 4, 6 )\n\n    QuadraticSpline2d.derivative exampleSpline 0.5\n    --> Vector2d.fromComponents ( 4, 0 )\n\n    QuadraticSpline2d.derivative exampleSpline 1\n    --> Vector2d.fromComponents ( 4, -6 )\n\nNote that the derivative interpolates linearly from end to end.\n\n",
                "type": "QuadraticSpline2d -> Float -> Vector2d"
            },
            {
                "name": "derivativeMagnitude",
                "comment": " Find the magnitude of the derivative to a spline at a particular parameter\nvalue;\n\n    QuadraticSpline2d.derivativeMagnitude spline t\n\nis equivalent to\n\n    Vector2d.length (QuadraticSpline2d.derivative spline t)\n\nbut more efficient since it avoids any intermediate `Vector2d` allocation.\n\n",
                "type": "QuadraticSpline2d -> Float -> Float"
            },
            {
                "name": "endDerivative",
                "comment": " Get the end derivative of a spline. This is equal to twice the vector from\nthe spline's second control point to its third.\n\n    QuadraticSpline2d.endDerivative exampleSpline\n    --> Vector2d.fromComponents ( 4, -6 )\n\n",
                "type": "QuadraticSpline2d -> Vector2d"
            },
            {
                "name": "endPoint",
                "comment": " Get the end point of a spline. This is equal to the spline's last control\npoint.\n\n    QuadraticSpline2d.endPoint exampleSpline\n    --> Point2d.fromCoordinates ( 5, 1 )\n\n",
                "type": "QuadraticSpline2d -> Point2d"
            },
            {
                "name": "evaluate",
                "comment": " Evaluate a spline at a given parameter value, returning the point on the\nspline at that parameter value and the derivative with respect to that parameter\nvalue;\n\n    QuadraticSpline2d.evaluate spline t\n\nis equivalent to\n\n    ( QuadraticSpline2d.pointOn spline t\n    , QuadraticSpline2d.derivative spline t\n    )\n\nbut is more efficient.\n\n",
                "type": "QuadraticSpline2d -> Float -> ( Point2d, Vector2d )"
            },
            {
                "name": "fromControlPoints",
                "comment": " Construct a spline from its three control points:\n\n    exampleSpline =\n        QuadraticSpline2d.fromControlPoints\n            ( Point2d.fromCoordinates ( 1, 1 )\n            , Point2d.fromCoordinates ( 3, 4 )\n            , Point2d.fromCoordinates ( 5, 1 )\n            )\n\n",
                "type": "( Point2d, Point2d, Point2d ) -> QuadraticSpline2d"
            },
            {
                "name": "mirrorAcross",
                "comment": " Mirror a spline across an axis.\n\n    QuadraticSpline2d.mirrorAcross Axis2d.x exampleSpline\n    --> QuadraticSpline2d.fromControlPoints\n    -->     ( Point2d.fromCoordinates ( 1, -1 )\n    -->     , Point2d.fromCoordinates ( 3, -4 )\n    -->     , Point2d.fromCoordinates ( 5, -1 )\n    -->     )\n\n",
                "type": "Axis2d -> QuadraticSpline2d -> QuadraticSpline2d"
            },
            {
                "name": "parameterValueToArcLength",
                "comment": " Try to get the arc length along a spline at a given parameter value. If the\ngiven parameter value is less than zero or greater than one, returns `Nothing`.\n\n    QuadraticSpline2d.parameterValueToArcLength\n        parameterizedSpline\n        0.25\n    --> Just 1.5122\n\n",
                "type": "ArcLengthParameterized -> Float -> Maybe Float"
            },
            {
                "name": "placeIn",
                "comment": " Take a spline considered to be defined in local coordinates relative to a\ngiven reference frame, and return that spline expressed in global coordinates.\n\n    localFrame =\n        Frame2d.atPoint (Point2d.fromCoordinates ( 1, 2 ))\n\n    QuadraticSpline2d.placeIn localFrame exampleSpline\n    --> QuadraticSpline2d.fromControlPoints\n    -->     ( Point2d.fromCoordinates ( 2, 3 )\n    -->     , Point2d.fromCoordinates ( 4, 6 )\n    -->     , Point2d.fromCoordinates ( 6, 3 )\n    -->     )\n\n",
                "type": "Frame2d -> QuadraticSpline2d -> QuadraticSpline2d"
            },
            {
                "name": "pointAlong",
                "comment": " Try to get the point along a spline at a given arc length. For example, to\nget the point a quarter of the way along `exampleSpline`:\n\n    QuadraticSpline2d.pointAlong parameterizedSpline\n        (arcLength / 4)\n    --> Just (Point2d.fromCoordinates ( 1.8350, 1.9911 ))\n\nNote that this is not the same as evaulating at a parameter value of 1/4:\n\n    QuadraticSpline2d.pointOn exampleSpline 0.25\n    --> Point2d.fromCoordinates ( 2, 2.125 )\n\nIf the given arc length is less than zero or greater than the arc length of the\nspline, `Nothing` is returned.\n\n",
                "type": "ArcLengthParameterized -> Float -> Maybe Point2d"
            },
            {
                "name": "pointOn",
                "comment": " Get a point along a spline, based on a parameter that ranges from 0 to 1. A\nparameter value of 0 corresponds to the start point of the spline and a value of\n1 corresponds to the end point.\n\n    QuadraticSpline2d.pointOn exampleSpline 0\n    --> Point2d.fromCoordinates ( 1, 1 )\n\n    QuadraticSpline2d.pointOn exampleSpline 0.5\n    --> Point2d.fromCoordinates ( 3, 2.5 )\n\n    QuadraticSpline2d.pointOn exampleSpline 1\n    --> Point2d.fromCoordinates ( 5, 1 )\n\n",
                "type": "QuadraticSpline2d -> Float -> Point2d"
            },
            {
                "name": "relativeTo",
                "comment": " Take a spline defined in global coordinates, and return it expressed in\nlocal coordinates relative to a given reference frame.\n\n    localFrame =\n        Frame2d.atPoint (Point2d.fromCoordinates ( 1, 2 ))\n\n    QuadraticSpline2d.relativeTo localFrame exampleSpline\n    --> QuadraticSpline2d.fromControlPoints\n    -->     ( Point2d.fromCoordinates ( 0, -1 )\n    -->     , Point2d.fromCoordinates ( 2, 2 )\n    -->     , Point2d.fromCoordinates ( 4, -1 )\n    -->     )\n\n",
                "type": "Frame2d -> QuadraticSpline2d -> QuadraticSpline2d"
            },
            {
                "name": "reverse",
                "comment": " Reverse a spline so that the start point becomes the end point, and vice\nversa.\n\n    QuadraticSpline2d.reverse exampleSpline\n    --> QuadraticSpline2d.fromControlPoints\n    -->     ( Point2d.fromCoordinates ( 5, 1 )\n    -->     , Point2d.fromCoordinates ( 3, 4 )\n    -->     , Point2d.fromCoordinates ( 1, 1 )\n    -->     )\n\n",
                "type": "QuadraticSpline2d -> QuadraticSpline2d"
            },
            {
                "name": "rotateAround",
                "comment": " Rotate a spline counterclockwise around a given center point by a given\nangle (in radians).\n\n    examplePolyline\n        |> QuadraticSpline2d.rotateAround Point2d.origin\n            (degrees 90)\n    --> QuadraticSpline2d.fromControlPoints\n    -->     ( Point2d.fromCoordinates ( -1, 1 )\n    -->     , Point2d.fromCoordinates ( -4, 3 )\n    -->     , Point2d.fromCoordinates ( -1, 5 )\n    -->     )\n\n",
                "type": "Point2d -> Float -> QuadraticSpline2d -> QuadraticSpline2d"
            },
            {
                "name": "scaleAbout",
                "comment": " Scale a spline about the given center point by the given scale.\n\n    examplePolyline\n        |> QuadraticSpline2d.scaleAbout Point2d.origin 2\n    --> QuadraticSpline2d.fromControlPoints\n    -->     ( Point2d.fromCoordinates ( 2, 2 )\n    -->     , Point2d.fromCoordinates ( 6, 8 )\n    -->     , Point2d.fromCoordinates ( 10, 2 )\n    -->     )\n\n",
                "type": "Point2d -> Float -> QuadraticSpline2d -> QuadraticSpline2d"
            },
            {
                "name": "secondDerivative",
                "comment": " Get the second derivative of a spline (for a quadratic spline, this is a\nconstant).\n",
                "type": "QuadraticSpline2d -> Vector2d"
            },
            {
                "name": "splitAt",
                "comment": " Split a spline at a particular parameter value (in the range 0 to 1),\nresulting in two smaller splines.\n\n    QuadraticSpline2d.splitAt 0.75 exampleSpline\n    --> ( QuadraticSpline2d.fromControlPoints\n    -->     ( Point2d.fromCoordinates ( 1, 1 )\n    -->     , Point2d.fromCoordinates ( 2.5, 3.25 )\n    -->     , Point2d.fromCoordinates ( 4, 2.125 )\n    -->     )\n    --> , QuadraticSpline2d.fromControlPoints\n    -->     ( Point2d.fromCoordinates ( 4, 2.125 )\n    -->     , Point2d.fromCoordinates ( 4.5, 1.75 )\n    -->     , Point2d.fromCoordinates ( 5, 1 )\n    -->     )\n    --> )\n\n",
                "type": "Float -> QuadraticSpline2d -> ( QuadraticSpline2d, QuadraticSpline2d )"
            },
            {
                "name": "startDerivative",
                "comment": " Get the start derivative of a spline. This is equal to twice the vector from\nthe spline's first control point to its second.\n\n    QuadraticSpline2d.startDerivative exampleSpline\n    --> Vector2d.fromComponents ( 4, 6 )\n\n",
                "type": "QuadraticSpline2d -> Vector2d"
            },
            {
                "name": "startPoint",
                "comment": " Get the start point of a spline. This is equal to the spline's first control\npoint.\n\n    QuadraticSpline2d.startPoint exampleSpline\n    --> Point2d.fromCoordinates ( 1, 1 )\n\n",
                "type": "QuadraticSpline2d -> Point2d"
            },
            {
                "name": "tangentAlong",
                "comment": " Try to get the tangent direction along a spline at a given arc length. To\nget the tangent direction a quarter of the way along `exampleSpline`:\n\n    QuadraticSpline2d.tangentAlong parameterizedSpline\n        (arcLength / 4)\n    --> Just (Direction2d.fromAngle (degrees 41.145))\n\nIf the given arc length is less than zero or greater than the arc length of the\nspline (or if the derivative of the spline happens to be exactly zero at the\ngiven arc length), `Nothing` is returned.\n\n",
                "type": "ArcLengthParameterized -> Float -> Maybe Direction2d"
            },
            {
                "name": "translateBy",
                "comment": " Translate a spline by a given displacement.\n\n    displacement =\n        Vector2d.fromComponents ( 2, 3 )\n\n    exampleSpline\n        |> QuadraticSpline2d.translateBy displacement\n    --> QuadraticSpline2d.fromControlPoints\n    -->     ( Point2d.fromCoordinates ( 3, 4 )\n    -->     , Point2d.fromCoordinates ( 5, 7 )\n    -->     , Point2d.fromCoordinates ( 7, 4 )\n    -->     )\n\n",
                "type": "Vector2d -> QuadraticSpline2d -> QuadraticSpline2d"
            }
        ],
        "binops": []
    },
    {
        "name": "OpenSolid.Circle2d",
        "comment": " <img src=\"https://opensolid.github.io/images/geometry/icons/circle2d.svg\" alt=\"Circle2d\" width=\"160\">\n\nA `Circle2d` is defined by its center point and radius. This module includes\nfunctionality for\n\n  - Constructing circles through points or with a given center/radius\n  - Scaling, rotating and translating circles\n  - Extracting properties of circles like area, center point and radius\n\n@docs Circle2d\n\n\n# Constants\n\n@docs unit\n\n\n# Constructors\n\n@docs with, throughPoints\n\n\n# Properties\n\n@docs centerPoint, radius, diameter, area, circumference, boundingBox\n\n\n# Conversion\n\n@docs toArc\n\n\n# Queries\n\n@docs contains\n\n\n# Transformations\n\n@docs scaleAbout, rotateAround, translateBy, mirrorAcross\n\n\n# Coordinate conversions\n\n@docs relativeTo, placeIn\n\n",
        "unions": [],
        "aliases": [
            {
                "name": "Circle2d",
                "comment": " ",
                "args": [],
                "type": "Circle2d"
            }
        ],
        "values": [
            {
                "name": "area",
                "comment": " Get the area of a circle.\n\n    Circle2d.area exampleCircle\n    --> 28.2743\n\n",
                "type": "Circle2d -> Float"
            },
            {
                "name": "boundingBox",
                "comment": " Get the minimal bounding box containing a given circle.\n\n    Circle2d.boundingBox exampleCircle\n    --> BoundingBox2d.with\n    -->     { minX = -2\n    -->     , maxX = 4\n    -->     , minY = -1\n    -->     , maxY = 5\n    -->     }\n\n",
                "type": "Circle2d -> BoundingBox2d"
            },
            {
                "name": "centerPoint",
                "comment": " Get the center point of a circle.\n\n    Circle2d.centerPoint exampleCircle\n    --> Point2d.fromCoordinates ( 1, 2 )\n\n",
                "type": "Circle2d -> Point2d"
            },
            {
                "name": "circumference",
                "comment": " Get the circumference of a circle.\n\n    Circle2d.circumference exampleCircle\n    --> 18.8496\n\n",
                "type": "Circle2d -> Float"
            },
            {
                "name": "contains",
                "comment": " Check if a circle contains a given point.\n\n    Circle2d.contains Point2d.origin exampleCircle\n    --> True\n\n    exampleCircle\n        |> Circle2d.contains\n            (Point2d.fromCoordinates ( 10, 10 ))\n    --> False\n\n",
                "type": "Point2d -> Circle2d -> Bool"
            },
            {
                "name": "diameter",
                "comment": " Get the diameter of a circle.\n\n    Circle2d.diameter exampleCircle\n    --> 6\n\n",
                "type": "Circle2d -> Float"
            },
            {
                "name": "mirrorAcross",
                "comment": " Mirror a circle across a given axis.\n\n    Circle2d.mirrorAcross Axis2d.x exampleCircle\n    --> Circle2d.with\n    -->     { centerPoint =\n    -->         Point2d.fromCoordinates ( 1, -2 )\n    -->     , radius = 3\n    -->     }\n\n",
                "type": "Axis2d -> Circle2d -> Circle2d"
            },
            {
                "name": "placeIn",
                "comment": " Take a circle considered to be defined in local coordinates relative to a\ngiven reference frame, and return that circle expressed in global coordinates.\n\n    localFrame =\n        Frame2d.atPoint (Point2d.fromCoordinates ( 2, 3 ))\n\n    Circle2d.placeIn localFrame exampleCircle\n    --> Circle2d.with\n    -->     { centerPoint =\n    -->         Point2d.fromCoordinates ( 3, 5 )\n    -->     , radius = 3\n    -->     }\n\n",
                "type": "Frame2d -> Circle2d -> Circle2d"
            },
            {
                "name": "radius",
                "comment": " Get the radius of a circle.\n\n    Circle2d.radius exampleCircle\n    --> 3\n\n",
                "type": "Circle2d -> Float"
            },
            {
                "name": "relativeTo",
                "comment": " Take a circle defined in global coordinates, and return it expressed in\nlocal coordinates relative to a given reference frame.\n\n    localFrame =\n        Frame2d.atPoint (Point2d.fromCoordinates ( 2, 3 ))\n\n    Circle2d.relativeTo localFrame exampleCircle\n    --> Circle2d.with\n    -->     { centerPoint =\n    -->         Point2d.fromCoordinates ( -1, -1 )\n    -->     , radius = 3\n    -->     }\n\n",
                "type": "Frame2d -> Circle2d -> Circle2d"
            },
            {
                "name": "rotateAround",
                "comment": " Rotate a circle around a given point by a given angle (in radians).\n\n    exampleCircle\n        |> Circle2d.rotateAround Point2d.origin\n            (degrees 90)\n    --> Circle2d.with\n    -->     { centerPoint =\n    -->         Point2d.fromCoordinates ( -2, 1 )\n    -->     , radius = 3\n    -->     }\n\n",
                "type": "Point2d -> Float -> Circle2d -> Circle2d"
            },
            {
                "name": "scaleAbout",
                "comment": " Scale a circle about a given point by a given scale.\n\n    Circle2d.scaleAbout Point2d.origin 2 exampleCircle\n    --> Circle2d.with\n    -->     { centerPoint =\n    -->         Point2d.fromCoordinates ( 2, 4 )\n    -->     , radius = 6\n    -->     }\n\n    exampleCircle\n        |> Circle2d.scaleAbout\n            (Point2d.fromCoordinates ( 1, 2 ))\n            0.5\n    --> Circle2d.with\n    -->     { centerPoint =\n    -->         Point2d.fromCoordinates ( 1, 2 )\n    -->     , radius = 1.5\n    -->     }\n\n",
                "type": "Point2d -> Float -> Circle2d -> Circle2d"
            },
            {
                "name": "throughPoints",
                "comment": " Attempt to construct a circle that passes through the three given points. If\nthe three given points are collinear, returns `Nothing`.\n\n    Circle2d.throughPoints\n        ( Point2d.origin\n        , Point2d.fromCoordinates ( 1, 0 )\n        , Point2d.fromCoordinates ( 0, 1 )\n        )\n    --> Just\n    -->     (Circle2d.with\n    -->         { centerPoint =\n    -->             Point2d.fromCoordinates ( 0.5, 0.5 )\n    -->         , radius = 0.7071\n    -->         }\n    -->     )\n\n    Circle2d.throughPoints\n        ( Point2d.origin\n        , Point2d.fromCoordinates ( 2, 1 )\n        , Point2d.fromCoordinates ( 4, 0 )\n        )\n    --> Just\n    -->     (Circle2d.with\n    -->         { centerPoint =\n    -->             Point2d.fromCoordinates ( 2, -1.5 )\n    -->         , radius = 2.5\n    -->         }\n    -->     )\n\n    Circle2d.throughPoints\n        ( Point2d.origin\n        , Point2d.fromCoordinates ( 2, 0 )\n        , Point2d.fromCoordinates ( 4, 0 )\n        )\n    --> Nothing\n\n    Circle2d.throughPoints\n        ( Point2d.origin\n        , Point2d.origin\n        , Point2d.fromCoordinates ( 1, 0 )\n        )\n    --> Nothing\n\n",
                "type": "( Point2d, Point2d, Point2d ) -> Maybe Circle2d"
            },
            {
                "name": "toArc",
                "comment": " Convert a circle to a 360 degree arc.\n\n    Circle2d.toArc exampleCircle\n    --> Arc2d.with\n    -->     { centerPoint =\n    -->         Point2d.fromCoordinates ( 1, 2 )\n    -->     , startPoint =\n    -->         Point2d.fromCoordinates ( 4, 2 )\n    -->     , sweptAngle = degrees 360\n    -->     }\n\n",
                "type": "Circle2d -> Arc2d"
            },
            {
                "name": "translateBy",
                "comment": " Translate a circle by a given displacement.\n\n    exampleCircle\n        |> Circle2d.translateBy\n            (Vector2d.fromComponents ( 2, 2 ))\n    --> Circle2d.with\n    -->     { centerPoint =\n    -->         Point2d.fromCoordinates ( 3, 4 )\n    -->     , radius = 3\n    -->     }\n\n",
                "type": "Vector2d -> Circle2d -> Circle2d"
            },
            {
                "name": "unit",
                "comment": " The unit circle, centered on the origin with a radius of 1.\n\n    Circle2d.unit\n    --> Circle2d.with\n    -->     { centerPoint = Point2d.origin\n    -->     , radius = 1\n    -->     }\n\n",
                "type": "Circle2d"
            },
            {
                "name": "with",
                "comment": " Construct a circle from its center point and radius:\n\n    exampleCircle =\n        Circle2d.with\n            { centerPoint =\n                Point2d.fromCoordinates ( 1, 2 )\n            , radius = 3\n            }\n\nThe actual radius of the circle will be the absolute value of the given radius\n(passing `radius = -2` will have the same effect as `radius = 2`).\n\n",
                "type": "{ centerPoint : Point2d, radius : Float } -> Circle2d"
            }
        ],
        "binops": []
    },
    {
        "name": "OpenSolid.Axis3d",
        "comment": " <img src=\"https://opensolid.github.io/images/geometry/icons/axis3d.svg\" alt=\"Axis3d\" width=\"160\">\n\nAn `Axis3d` represents an infinitely long straight line in 3D and is defined by\nan origin point and direction. Axes have several uses, such as:\n\n  - Rotating around the axis\n  - Projecting onto the axis\n  - Measuring distance along the axis\n\n@docs Axis3d\n\n\n# Constants\n\n@docs x, y, z\n\n\n# Constructors\n\n@docs with, on\n\n\n# Properties\n\n@docs originPoint, direction\n\n\n# Transformations\n\n@docs flip, moveTo, rotateAround, translateBy, mirrorAcross, projectOnto\n\n\n# Coordinate conversions\n\nFunctions for transforming axes between local and global coordinates in\ndifferent coordinate frames.\n\n@docs relativeTo, placeIn, projectInto\n\n",
        "unions": [],
        "aliases": [
            {
                "name": "Axis3d",
                "comment": " ",
                "args": [],
                "type": "Axis3d"
            }
        ],
        "values": [
            {
                "name": "direction",
                "comment": " Get the direction of an axis.\n\n    Axis3d.direction exampleAxis\n    --> Direction3d.y\n\n",
                "type": "Axis3d -> Direction3d"
            },
            {
                "name": "flip",
                "comment": " Reverse the direction of an axis while keeping the same origin point.\n\n    Axis3d.flip exampleAxis\n    --> Axis3d.with\n    -->     { originPoint =\n    -->         Point3d.fromCoordinates ( 1, 2, 3 )\n    -->     , direction = Direction3d.negativeY\n    -->     }\n\n",
                "type": "Axis3d -> Axis3d"
            },
            {
                "name": "mirrorAcross",
                "comment": " Mirror an axis across a plane.\n\n    Axis3d.mirrorAcross Plane3d.xy exampleAxis\n    --> Axis3d.with\n    -->     { originPoint =\n    -->         Point3d.fromCoordinates ( 1, 2, -3 )\n    -->     , direction = Direction3d.y\n    -->     }\n\n",
                "type": "Plane3d -> Axis3d -> Axis3d"
            },
            {
                "name": "moveTo",
                "comment": " Move an axis so that it has the given origin point but unchanged direction.\n\n    newOrigin =\n        Point3d.fromCoordinates ( 3, 4, 5 )\n\n    Axis3d.moveTo newOrigin exampleAxis\n    --> Axis3d.with\n    -->     { originPoint =\n    -->         Point3d.fromCoordinates ( 3, 4, 5 )\n    -->     , direction = Direction3d.y\n    -->     }\n\n",
                "type": "Point3d -> Axis3d -> Axis3d"
            },
            {
                "name": "on",
                "comment": " Construct a 3D axis lying _on_ a sketch plane by providing a 2D axis\nspecified in XY coordinates _within_ the sketch plane.\n\n    axis2d =\n        Axis2d.with\n            { originPoint =\n                Point2d.fromCoordinates ( 1, 3 )\n            , direction =\n                Direction2d.fromAngle (degrees 30)\n            }\n\n    Axis3d.on SketchPlane3d.xy axis2d\n    --> Axis3d.with\n    -->     { originPoint =\n    -->         Point3d.fromCoordinates ( 1, 3, 0 )\n    -->     , direction =\n    -->         Direction3d.with\n    -->             { azimuth = degrees 30\n    -->             , elevation = 0\n    -->             }\n    -->     }\n\n    Axis3d.on SketchPlane3d.zx axis2d\n    --> Axis3d.with\n    -->     { originPoint =\n    -->         Point3d.fromCoordinates ( 3, 0, 1 )\n    -->     , direction =\n    -->         Direction3d.with\n    -->             { azimuth = 0\n    -->             , elevation = degrees 60\n    -->             }\n    -->     }\n\n",
                "type": "SketchPlane3d -> Axis2d -> Axis3d"
            },
            {
                "name": "originPoint",
                "comment": " Get the origin point of an axis.\n\n    Axis3d.originPoint exampleAxis\n    --> Point3d.fromCoordinates ( 1, 2, 3 )\n\n",
                "type": "Axis3d -> Point3d"
            },
            {
                "name": "placeIn",
                "comment": " Take an axis defined in local coordinates relative to a given reference\nframe, and return that axis expressed in global coordinates.\n\n    localFrame =\n        Frame3d.atPoint\n            (Point3d.fromCoordinates ( 3, 3, 3 ))\n\n    Axis3d.placeIn localFrame exampleAxis\n    --> Axis3d.with\n    -->     { originPoint =\n    -->         Point3d.fromCoordinates ( 4, 5, 6 )\n    -->     , direction = Direction3d.y\n    -->     }\n\n",
                "type": "Frame3d -> Axis3d -> Axis3d"
            },
            {
                "name": "projectInto",
                "comment": " Project an axis into a given sketch plane. Conceptually, this finds the\n[orthographic projection](https://en.wikipedia.org/wiki/Orthographic_projection)\nof the axis onto the plane and then expresses the projected axis in 2D sketch\ncoordinates.\n\nThis is only possible if the axis is not perpendicular to the sketch\nplane; if it is perpendicular, `Nothing` is returned.\n\n    Axis3d.projectInto SketchPlane3d.xy exampleAxis\n    --> Just\n    -->     (Axis2d.with\n    -->         { originPoint =\n    -->             Point2d.fromCoordinates ( 1, 2 )\n    -->         , direction = Direction2d.y\n    -->         }\n    -->     )\n\n    Axis3d.projectInto SketchPlane3d.yz exampleAxis\n    --> Just\n    -->     (Axis2d.with\n    -->         { originPoint =\n    -->             Point2d.fromCoordinates ( 2, 3 )\n    -->         -- The global Y direction is the X\n    -->         -- direction of the YZ plane:\n    -->         , direction = Direction2d.x\n    -->         }\n    -->     )\n\n    Axis3d.projectInto SketchPlane3d.xz exampleAxis\n    --> Nothing\n\n",
                "type": "SketchPlane3d -> Axis3d -> Maybe Axis2d"
            },
            {
                "name": "projectOnto",
                "comment": " Find the [orthographic projection](https://en.wikipedia.org/wiki/Orthographic_projection)\nof an axis onto a plane. If the given axis is exactly perpendicular to the given\nplane, returns `Nothing`.\n\n    Axis3d.projectOnto Plane3d.xy exampleAxis\n    --> Just\n    -->     (Axis3d.with\n    -->         { originPoint =\n    -->             Point3d.fromCoordinates ( 1, 2, 0 )\n    -->         , direction = Direction3d.y\n    -->         }\n    -->     )\n\n    Axis3d.projectOnto Plane3d.xy Axis3d.z\n    --> Nothing\n\n",
                "type": "Plane3d -> Axis3d -> Maybe Axis3d"
            },
            {
                "name": "relativeTo",
                "comment": " Take an axis defined in global coordinates, and return it expressed in local\ncoordinates relative to a given reference frame.\n\n    localFrame =\n        Frame3d.atPoint\n            (Point3d.fromCoordinates ( 3, 3, 3 ))\n\n    Axis3d.relativeTo localFrame exampleAxis\n    --> Axis3d.with\n    -->     { originPoint =\n    -->         Point3d.fromCoordinates ( -2, -1, 0 )\n    -->     , direction = Direction3d.y\n    -->     }\n\n",
                "type": "Frame3d -> Axis3d -> Axis3d"
            },
            {
                "name": "rotateAround",
                "comment": " Rotate an axis around another axis by a given angle. The axis to rotate\naround is given first and the axis to rotate is given last.\n\n    Axis3d.rotateAround Axis3d.z (degrees 90) exampleAxis\n    --> Axis3d.with\n    -->     { originPoint =\n    -->         Point3d.fromCoordinates ( -2, 1, 3 )\n    -->     , direction = Direction3d.negativeX\n    -->     }\n\n",
                "type": "Axis3d -> Float -> Axis3d -> Axis3d"
            },
            {
                "name": "translateBy",
                "comment": " Translate an axis by a given displacement. Applies the given displacement to\nthe axis' origin point and leaves the direction unchanged.\n\n    displacement =\n        Vector3d.fromComponents ( 3, 3, 3 )\n\n    Axis3d.translateBy displacement exampleAxis\n    --> Axis3d.with\n    -->     { originPoint =\n    -->         Point3d.fromCoordinates ( 4, 5, 6 )\n    -->     , direction = Direction3d.y\n    -->     }\n\n",
                "type": "Vector3d -> Axis3d -> Axis3d"
            },
            {
                "name": "with",
                "comment": " Construct an axis from its origin point and direction:\n\n    exampleAxis =\n        Axis3d.with\n            { originPoint =\n                Point3d.fromCoordinates ( 1, 2, 3 )\n            , direction = Direction3d.y\n            }\n\n",
                "type": "{ originPoint : Point3d, direction : Direction3d } -> Axis3d"
            },
            {
                "name": "x",
                "comment": " The global X axis.\n\n    Axis3d.x\n    --> Axis3d.with\n    -->     { originPoint = Point3d.origin\n    -->     , direction = Direction3d.x\n    -->     }\n\n",
                "type": "Axis3d"
            },
            {
                "name": "y",
                "comment": " The global Y axis.\n\n    Axis3d.y\n    --> Axis3d.with\n    -->     { originPoint = Point3d.origin\n    -->     , direction = Direction3d.y\n    -->     }\n\n",
                "type": "Axis3d"
            },
            {
                "name": "z",
                "comment": " The global Z axis.\n\n    Axis3d.z\n    --> Axis3d.with\n    -->     { originPoint = Point3d.origin\n    -->     , direction = Direction3d.z\n    -->     }\n\n",
                "type": "Axis3d"
            }
        ],
        "binops": []
    },
    {
        "name": "OpenSolid.Frame2d",
        "comment": " <img src=\"https://opensolid.github.io/images/geometry/icons/frame2d.svg\" alt=\"Frame2d\" width=\"160\">\n\nA `Frame2d` has an origin point and a pair of X and Y directions (which are\nalways perpendicular to each other). It can be thought of as:\n\n  - A local coordinate system: Most geometric types have associated `relativeTo`\n    and `placeIn` functions that convert values of that type from global\n    coordinates to local coordinates in a particular frame, and vice versa.\n  - A pair of X and Y axes: It is often convenient to (for example) mirror\n    across the X axis of a frame, or project onto its Y axis. Frames can\n    also themselves be translated, rotated and mirrored!\n  - A combined 2D position and orientation: For example, a `Frame2d` could be\n    used to define the position and orientation of a spaceship in a 2D game.\n    Movement of the ship would then be done by translating and rotating the\n    frame.\n\n@docs Frame2d\n\n\n# Constants\n\n@docs xy\n\n\n# Constructors\n\n@docs atPoint, with, unsafe\n\n\n# Properties\n\n@docs originPoint, xDirection, yDirection, isRightHanded, xAxis, yAxis\n\n\n# Transformations\n\n@docs flipX, flipY, moveTo, rotateBy, rotateAround, translateBy, translateAlongOwn, mirrorAcross\n\n\n# Coordinate conversions\n\n@docs relativeTo, placeIn\n\n",
        "unions": [],
        "aliases": [
            {
                "name": "Frame2d",
                "comment": " ",
                "args": [],
                "type": "Frame2d"
            }
        ],
        "values": [
            {
                "name": "atPoint",
                "comment": " Construct a frame aligned with the global XY frame but with the given origin\npoint.\n\n    point =\n        Point2d.fromCoordinates ( 2, 3 )\n\n    frame =\n        Frame2d.atPoint point\n\n    Frame2d.originPoint frame\n    --> point\n\n    Frame2d.xDirection frame\n    --> Direction2d.x\n\n    Frame2d.yDirection frame\n    --> Direction2d.y\n\n",
                "type": "Point2d -> Frame2d"
            },
            {
                "name": "flipX",
                "comment": " Reverse the X direction of a frame, leaving its Y direction and origin point\nthe same.\n\n    point =\n        Point2d.fromCoordinates ( 2, 3 )\n\n    frame =\n        Frame2d.atPoint point |> Frame2d.flipX\n\n    Frame2d.originPoint frame\n    --> point\n\n    Frame2d.xDirection frame\n    --> Direction2d.negativeX\n\n    Frame2d.yDirection frame\n    --> Direction2d.y\n\nNote that this will switch the [handedness](https://en.wikipedia.org/wiki/Cartesian_coordinate_system#Orientation_and_handedness)\nof the frame.\n\n",
                "type": "Frame2d -> Frame2d"
            },
            {
                "name": "flipY",
                "comment": " Reverse the Y direction of a frame, leaving its X direction and origin point\nthe same.\n\n    point =\n        Point2d.fromCoordinates ( 2, 3 )\n\n    frame =\n        Frame2d.atPoint point |> Frame2d.flipY\n\n    Frame2d.originPoint frame\n    --> point\n\n    Frame2d.xDirection frame\n    --> Direction2d.x\n\n    Frame2d.yDirection frame\n    --> Direction2d.negativeY\n\nNote that this will switch the [handedness](https://en.wikipedia.org/wiki/Cartesian_coordinate_system#Orientation_and_handedness)\nof the frame.\n\n",
                "type": "Frame2d -> Frame2d"
            },
            {
                "name": "isRightHanded",
                "comment": " Check if a frame is [right-handed](https://en.wikipedia.org/wiki/Cartesian_coordinate_system#Orientation_and_handedness).\n\n    Frame2d.isRightHanded Frame2d.xy\n    --> True\n\n    Frame2d.isRightHanded (Frame2d.flipX Frame2d.xy)\n    --> False\n\nAll predefined frames are right-handed, and most operations on frames preserve\nhandedness, so about the only ways to end up with a left-handed frame are by\nconstructing one explicitly with `unsafe` or by mirroring a right-handed frame.\n\n",
                "type": "Frame2d -> Bool"
            },
            {
                "name": "mirrorAcross",
                "comment": " Mirror a frame across an axis.\n\n    frame =\n        Frame2d.atPoint (Point2d.fromCoordinates ( 2, 3 ))\n\n    mirroredFrame =\n        Frame2d.mirrorAcross Axis2d.x frame\n\n    Frame2d.originPoint mirroredFrame\n    --> Point2d.fromCoordinates ( 2, -3 )\n\n    Frame2d.xDirection mirroredFrame\n    --> Direction2d.x\n\n    Frame2d.yDirection mirroredFrame\n    --> Direction2d.negativeY\n\nNote that this will switch the [handedness](https://en.wikipedia.org/wiki/Cartesian_coordinate_system#Orientation_and_handedness)\nof the frame.\n\n",
                "type": "Axis2d -> Frame2d -> Frame2d"
            },
            {
                "name": "moveTo",
                "comment": " Move a frame so that it has the given origin point.\n\n    point =\n        Point2d.fromCoordinates ( 1, 1 )\n\n    Frame2d.xy |> Frame2d.moveTo point\n    --> Frame2d.atPoint point\n\n",
                "type": "Point2d -> Frame2d -> Frame2d"
            },
            {
                "name": "originPoint",
                "comment": " Get the origin point of a given frame.\n\n    Frame2d.originPoint Frame2d.xy\n    --> Point2d.origin\n\n",
                "type": "Frame2d -> Point2d"
            },
            {
                "name": "placeIn",
                "comment": " Take one frame defined in global coordinates and a second frame defined\nin local coordinates relative to the first frame, and return the second frame\nexpressed in global coordinates.\n",
                "type": "Frame2d -> Frame2d -> Frame2d"
            },
            {
                "name": "relativeTo",
                "comment": " Take two frames defined in global coordinates, and return the second one\nexpressed in local coordinates relative to the first.\n",
                "type": "Frame2d -> Frame2d -> Frame2d"
            },
            {
                "name": "rotateAround",
                "comment": " Rotate a frame counterclockwise around a given point by a given angle. The\nframe's origin point will be rotated around the given point by the given angle,\nand its X and Y basis directions will be rotated by the given angle.\n\n    rotatedFrame =\n        Frame2d.atPoint (Point2d.fromCoordinates ( 1, 1 ))\n            |> Frame2d.rotateAround Point2d.origin\n                (degrees 45)\n\n    Frame2d.originPoint rotatedFrame\n    --> Point2d.fromCoordinates ( 0, 1.4142 )\n\n    Frame2d.xDirection rotatedFrame\n    --> Direction2d.fromAngle (degrees 45)\n\n    Frame2d.yDirection rotatedFrame\n    --> Direction2d.fromAngle (degrees 135)\n\n",
                "type": "Point2d -> Float -> Frame2d -> Frame2d"
            },
            {
                "name": "rotateBy",
                "comment": " Rotate a frame counterclockwise by a given angle around the frame's own\norigin point. The resulting frame will have the same origin point, and its X and\nY directions will be rotated by the given angle.\n\n    rotatedFrame =\n        Frame2d.rotateBy (degrees 30) Frame2d.xy\n\n    Frame2d.xDirection rotatedFrame\n    --> Direction2d.fromAngle (degrees 30)\n\n    Frame2d.yDirection rotatedFrame\n    --> Direction2d.fromAngle (degrees 120)\n\n",
                "type": "Float -> Frame2d -> Frame2d"
            },
            {
                "name": "translateAlongOwn",
                "comment": " Translate a frame along one of its own axes by a given distance.\n\nThe first argument is a function that returns the axis to translate along, given\nthe current frame. The majority of the time this argument will be either\n`Frame2d.xAxis` or `Frame2d.yAxis`. The second argument is the distance to\ntranslate along the given axis.\n\nThis function is convenient when constructing frames via a series of\ntransformations. For example,\n\n    frame =\n        Frame2d.atPoint (Point2d.fromCoordinates ( 2, 0 ))\n            |> Frame2d.rotateBy (degrees 45)\n            |> Frame2d.translateAlongOwn Frame2d.xAxis 2\n\nmeans \"construct a frame at the point (2, 0), rotate it around its own origin\npoint by 45 degrees, then translate it along its own X axis by 2 units\",\nresulting in\n\n    Frame2d.originPoint frame\n    --> Point2d.fromCoordinates ( 3.4142, 1.4142 )\n\n    Frame2d.xDirection frame\n    --> Direction2d.fromAngle (degrees 45)\n\n    Frame2d.yDirection frame\n    --> Direction2d.fromAngle (degrees 135)\n\n",
                "type": "(Frame2d -> Axis2d) -> Float -> Frame2d -> Frame2d"
            },
            {
                "name": "translateBy",
                "comment": " Translate a frame by a given displacement.\n\n    frame =\n        Frame2d.atPoint (Point2d.fromCoordinates ( 2, 3 ))\n\n    displacement =\n        Vector2d.fromComponents ( 1, 1 )\n\n    Frame2d.translateBy displacement frame\n    --> Frame2d.atPoint (Point2d.fromCoordinates ( 3, 4 ))\n\n",
                "type": "Vector2d -> Frame2d -> Frame2d"
            },
            {
                "name": "unsafe",
                "comment": " Construct a frame directly from its origin point and X and Y directions:\n\n    frame =\n        Frame2d.unsafe\n            { originPoint =\n                Point2d.fromCoordinates ( 2, 3 )\n            , xDirection =\n                Direction2d.fromAngle (degrees 45)\n            , yDirection =\n                Direction2d.fromAngle (degrees 135)\n            }\n\nIn this case **you must be careful to ensure that the X and Y directions are\nperpendicular**. To construct pairs of perpendicular directions,\n[`Direction2d.orthonormalize`](OpenSolid-Direction2d#orthonormalize) or\n[`Direction2d.orthogonalize`](OpenSolid-Direction2d#orthogonalize) may be\nuseful.\n\n",
                "type": "{ originPoint : Point2d, xDirection : Direction2d, yDirection : Direction2d } -> Frame2d"
            },
            {
                "name": "with",
                "comment": " Construct a frame given its origin point and X axis direction. The Y axis\ndirection will be constructed by rotating the given X direction 90 degrees\ncounterclockwise:\n\n    frame =\n        Frame2d.with\n            { originPoint =\n                Point2d.fromCoordinates ( 2, 3 )\n            , xDirection =\n                Direction2d.fromAngle (degrees 30)\n            }\n\n    Frame2d.yDirection frame\n    --> Direction2d.fromAngle (degrees 120)\n\n",
                "type": "{ originPoint : Point2d, xDirection : Direction2d } -> Frame2d"
            },
            {
                "name": "xAxis",
                "comment": " Get the X axis of a given frame (the axis formed from the frame's origin\npoint and X direction).\n\n    Frame2d.xAxis Frame2d.xy\n    --> Axis2d.x\n\n",
                "type": "Frame2d -> Axis2d"
            },
            {
                "name": "xDirection",
                "comment": " Get the X direction of a given frame.\n\n    Frame2d.xDirection Frame2d.xy\n    --> Direction2d.x\n\n",
                "type": "Frame2d -> Direction2d"
            },
            {
                "name": "xy",
                "comment": " The global XY frame.\n\n    Frame2d.originPoint Frame2d.xy\n    --> Point2d.origin\n\n    Frame2d.xDirection Frame2d.xy\n    --> Direction2d.x\n\n    Frame2d.yDirection Frame2d.xy\n    --> Direction2d.y\n\n",
                "type": "Frame2d"
            },
            {
                "name": "yAxis",
                "comment": " Get the Y axis of a given frame (the axis formed from the frame's origin\npoint and Y direction).\n\n    Frame2d.yAxis Frame2d.xy\n    --> Axis2d.y\n\n",
                "type": "Frame2d -> Axis2d"
            },
            {
                "name": "yDirection",
                "comment": " Get the Y direction of a given frame.\n\n    Frame2d.yDirection Frame2d.xy\n    --> Direction2d.y\n\n",
                "type": "Frame2d -> Direction2d"
            }
        ],
        "binops": []
    },
    {
        "name": "OpenSolid.Point3d",
        "comment": " <img src=\"https://opensolid.github.io/images/geometry/icons/point3d.svg\" alt=\"Point3d\" width=\"160\">\n\nA `Point3d` represents a position in 3D space and is defined by its X, Y and Z\ncoordinates. This module contains a variety of point-related functionality, such\nas\n\n  - Measuring distance between points, or the distance of a point from an axis\n    or a plane\n  - Scaling, rotating, translating, mirroring and projecting points\n  - Converting points between different coordinate systems\n\nPoints are distinct from vectors but interact with them in well-defined ways;\nyou can translate a point by a vector to result in a new point, or you can\ncompute the vector from one point to another, but you cannot 'add' two points\nlike you can add two vectors.\n\n@docs Point3d\n\n\n# Constants\n\n@docs origin\n\n\n# Constructors\n\n@docs fromCoordinates, midpoint, interpolateFrom, along, on, in_, circumcenter\n\n\n# Properties\n\n@docs coordinates, xCoordinate, yCoordinate, zCoordinate\n\n\n# Comparison\n\n@docs equalWithin\n\n\n# Measurement\n\n@docs distanceFrom, squaredDistanceFrom, signedDistanceAlong, distanceAlong, distanceFromAxis, squaredDistanceFromAxis, signedDistanceFrom\n\n\n# Transformations\n\n@docs scaleAbout, rotateAround, translateBy, mirrorAcross, projectOnto, projectOntoAxis\n\n\n# Coordinate conversions\n\nFunctions for transforming points between local and global coordinates in\ndifferent coordinate frames.\n\n@docs relativeTo, placeIn, projectInto\n\n\n# Bounding box construction\n\n@docs hull, hullOf\n\n",
        "unions": [],
        "aliases": [
            {
                "name": "Point3d",
                "comment": " ",
                "args": [],
                "type": "Point3d"
            }
        ],
        "values": [
            {
                "name": "along",
                "comment": " Construct a point along an axis at a particular distance from the axis'\norigin point.\n\n    Point3d.along Axis3d.z 2\n    --> Point3d.fromCoordinates ( 0, 0, 2 )\n\nPositive and negative distances are interpreted relative to the direction of the\naxis:\n\n    horizontalAxis =\n        Axis3d.with\n            { originPoint =\n                Point3d.fromCoordinates ( 1, 1, 1 )\n            , direction = Direction3d.negativeX\n            }\n\n    Point3d.along horizontalAxis 3\n    --> Point3d.fromCoordinates ( -2, 1, 1 )\n\n    Point3d.along horizontalAxis -3\n    --> Point3d.fromCoordinates ( 4, 1, 1 )\n\n",
                "type": "Axis3d -> Float -> Point3d"
            },
            {
                "name": "circumcenter",
                "comment": " Attempt to find the circumcenter of three points; this is the center of the\ncircle that passes through all three points. If the three given points are\ncollinear, returns `Nothing`.\n\n    Point3d.circumcenter\n        ( Point3d.fromCoordinates ( 1, 0, 0 )\n        , Point3d.fromCoordinates ( 0, 1, 0 )\n        , Point3d.fromCoordinates ( 0, 0, 1 )\n        )\n    --> Just (Point3d.fromCoordinates (0.33, 0.33, 0.33))\n\n    Point3d.circumcenter\n        ( Point3d.origin\n        , Point3d.fromCoordinates ( 1, 0, 0 )\n        , Point3d.fromCoordinates ( 2, 0, 0 )\n        )\n    --> Nothing\n\n",
                "type": "( Point3d, Point3d, Point3d ) -> Maybe Point3d"
            },
            {
                "name": "coordinates",
                "comment": " Get the coordinates of a point as a tuple.\n\n    ( x, y, z ) =\n        Point3d.coordinates point\n\n",
                "type": "Point3d -> ( Float, Float, Float )"
            },
            {
                "name": "distanceAlong",
                "comment": " DEPRECATED: Alias for `signedDistanceAlong`, kept for compatibility. Use\n`signedDistanceAlong` instead.\n",
                "type": "Axis3d -> Point3d -> Float"
            },
            {
                "name": "distanceFrom",
                "comment": " Find the distance from the first point to the second.\n\n    p1 =\n        Point3d.fromCoordinates ( 1, 1, 2 )\n\n    p2 =\n        Point3d.fromCoordinates ( 2, 3, 4 )\n\n    Point3d.distanceFrom p1 p2\n    --> 3\n\nPartial application can be useful:\n\n    points =\n        [ Point3d.fromCoordinates ( 3, 4, 5 )\n        , Point3d.fromCoordinates ( 10, 10, 10 )\n        , Point3d.fromCoordinates ( -1, 2, -3 )\n        ]\n\n    points\n        |> List.sortBy\n            (Point3d.distanceFrom Point3d.origin)\n    --> [ Point3d.fromCoordinates ( -1, 2, -3 )\n    --> , Point3d.fromCoordinates ( 3, 4, 5 )\n    --> , Point3d.fromCoordinates ( 10, 10, 10 )\n    --> ]\n\n",
                "type": "Point3d -> Point3d -> Float"
            },
            {
                "name": "distanceFromAxis",
                "comment": " Find the perpendicular (nearest) distance of a point from an axis.\n\n    point =\n        Point3d.fromCoordinates ( -3, 4, 0 )\n\n    Point3d.distanceFromAxis Axis3d.x point\n    --> 4\n\n    Point3d.distanceFromAxis Axis3d.y point\n    --> 3\n\n    Point3d.distanceFromAxis Axis3d.z point\n    --> 5\n\nNote that unlike in 2D, the result is always positive (unsigned) since there is\nno such thing as the left or right side of an axis in 3D.\n\n",
                "type": "Axis3d -> Point3d -> Float"
            },
            {
                "name": "equalWithin",
                "comment": " Compare two points within a tolerance. Returns true if the distance\nbetween the two given points is less than the given tolerance.\n\n    firstPoint =\n        Point3d.fromCoordinates ( 2, 1, 3 )\n\n    secondPoint =\n        Point3d.fromCoordinates ( 2.0002, 0.9999, 3.0001 )\n\n    Point3d.equalWithin 1e-3 firstPoint secondPoint\n    --> True\n\n    Point3d.equalWithin 1e-6 firstPoint secondPoint\n    --> False\n\n",
                "type": "Float -> Point3d -> Point3d -> Bool"
            },
            {
                "name": "fromCoordinates",
                "comment": " Construct a point from its X, Y and Z coordinates.\n\n    point =\n        Point3d.fromCoordinates ( 2, 1, 3 )\n\n",
                "type": "( Float, Float, Float ) -> Point3d"
            },
            {
                "name": "hull",
                "comment": " Construct a bounding box containing both of the given points.\n\n    point1 =\n        Point3d.fromCoordinates ( 2, 1, 3 )\n\n    point2 =\n        Point3d.fromCoordinates ( -1, 5, -2 )\n\n    Point3d.hull point1 point2\n    --> BoundingBox3d.with\n    -->     { minX = -1\n    -->     , maxX = 2\n    -->     , minY = 1\n    -->     , maxY = 5\n    -->     , minZ = -2\n    -->     , maxZ = 3\n    -->     }\n\n",
                "type": "Point3d -> Point3d -> BoundingBox3d"
            },
            {
                "name": "hullOf",
                "comment": " Construct a bounding box containing all points in the given list. If the\nlist is empty, returns `Nothing`.\n\n    points =\n        [ Point3d.fromCoordinates ( 2, 1, 3 )\n        , Point3d.fromCoordinates ( -1, 5, -2 )\n        , Point3d.fromCoordinates ( 6, 4, 2 )\n        ]\n\n    Point3d.hullOf points\n    --> Just\n    -->     (BoundingBox3d.with\n    -->         { minX = -1\n    -->         , maxX = 6\n    -->         , minY = 1\n    -->         , maxY = 5\n    -->         , minZ = -2\n    -->         , maxZ = 3\n    -->         }\n    -->     )\n\n    Point3d.hullOf []\n    --> Nothing\n\n",
                "type": "List Point3d -> Maybe BoundingBox3d"
            },
            {
                "name": "in_",
                "comment": " Construct a point given its local coordinates within a particular frame.\n\n    frame =\n        Frame3d.atPoint\n            (Point3d.fromCoordinates ( 1, 1, 1 ))\n\n    Point3d.in_ frame ( 1, 2, 3 )\n    --> Point3d.fromCoordinates ( 2, 3, 4 )\n\nThis is shorthand for using `Point3d.placeIn`;\n\n    Point3d.in_ frame coordinates\n\nis equivalent to\n\n    Point3d.placeIn frame\n        (Point3d.fromCoordinates coordinates)\n\n",
                "type": "Frame3d -> ( Float, Float, Float ) -> Point3d"
            },
            {
                "name": "interpolateFrom",
                "comment": " Construct a point by interpolating from the first given point to the second,\nbased on a parameter that ranges from zero to one.\n\n    startPoint =\n        Point3d.fromCoordinates ( 1, 2, 4 )\n\n    endPoint =\n        Point3d.fromCoordinates ( 1, 2, 8 )\n\n    Point3d.interpolateFrom startPoint endPoint 0.25\n    --> Point3d.fromCoordinates ( 1, 2, 5 )\n\nPartial application may be useful:\n\n    interpolatedPoint : Float -> Point3d\n    interpolatedPoint =\n        Point3d.interpolateFrom startPoint endPoint\n\n    List.map interpolatedPoint [ 0, 0.5, 1 ]\n    --> [ Point3d.fromCoordinates ( 1, 2, 4 )\n    --> , Point3d.fromCoordinates ( 1, 2, 6 )\n    --> , Point3d.fromCoordinates ( 1, 2, 8 )\n    --> ]\n\nYou can pass values less than zero or greater than one to extrapolate:\n\n    interpolatedPoint -0.5\n    --> Point3d.fromCoordinates ( 1, 2, 2 )\n\n    interpolatedPoint 1.25\n    --> Point3d.fromCoordinates ( 1, 2, 9 )\n\n",
                "type": "Point3d -> Point3d -> Float -> Point3d"
            },
            {
                "name": "midpoint",
                "comment": " Construct a point halfway between two other points.\n\n    p1 =\n        Point3d.fromCoordinates ( 1, 1, 1 )\n\n    p2 =\n        Point3d.fromCoordinates ( 3, 7, 9 )\n\n    Point3d.midpoint p1 p2\n    --> Point3d.fromCoordinates ( 2, 4, 5 )\n\n",
                "type": "Point3d -> Point3d -> Point3d"
            },
            {
                "name": "mirrorAcross",
                "comment": " Mirror a point across a plane. The result will be the same distance from the\nplane but on the opposite side.\n\n    point =\n        Point3d.fromCoordinates ( 1, 2, 3 )\n\n    -- Plane3d.xy is the plane Z=0\n    Point3d.mirrorAcross Plane3d.xy point\n    --> Point3d.fromCoordinates ( 1, 2, -3 )\n\n    -- Plane3d.yz is the plane X=0\n    Point3d.mirrorAcross Plane3d.yz point\n    --> Point3d.fromCoordinates ( -1, 2, 3 )\n\nThe plane does not have to pass through the origin:\n\n    -- offsetPlane is the plane Z=1\n    offsetPlane =\n        Plane3d.offsetBy 1 Plane3d.xy\n\n    -- The origin point is 1 unit below the offset\n    -- plane, so its mirrored copy is one unit above\n    Point3d.mirrorAcross offsetPlane Point3d.origin\n    --> Point3d.fromCoordinates ( 0, 0, 2 )\n\n",
                "type": "Plane3d -> Point3d -> Point3d"
            },
            {
                "name": "on",
                "comment": " Construct a 3D point lying _on_ a sketch plane by providing a 2D point\nspecified in XY coordinates _within_ the sketch plane.\n\n    Point3d.on SketchPlane3d.xy <|\n        Point2d.fromCoordinates ( 2, 1 )\n    --> Point3d.fromCoordinates ( 2, 1, 0 )\n\n    Point3d.on SketchPlane3d.xz <|\n        Point2d.fromCoordinates ( 2, 1 )\n    --> Point3d.fromCoordinates ( 2, 0, 1 )\n\nThe sketch plane can have any position and orientation:\n\n    tiltedSketchPlane =\n        SketchPlane3d.xy\n            |> SketchPlane3d.rotateAround Axis3d.x\n                (degrees 45)\n            |> SketchPlane3d.moveTo\n                (Point3d.fromCoordinates ( 10, 10, 10 ))\n\n    Point3d.on tiltedSketchPlane <|\n        Point2d.fromCoordinates ( 2, 1 )\n    --> Point3d.fromCoordinates ( 12, 10.7071, 10.7071 )\n\n",
                "type": "SketchPlane3d -> Point2d -> Point3d"
            },
            {
                "name": "origin",
                "comment": " The point (0, 0, 0).\n\n    Point3d.origin\n    --> Point3d.fromCoordinates ( 0, 0, 0 )\n\n",
                "type": "Point3d"
            },
            {
                "name": "placeIn",
                "comment": " Take a point defined in local coordinates relative to a given reference\nframe, and return that point expressed in global coordinates.\n\n    localFrame =\n        Frame3d.atPoint\n            (Point3d.fromCoordinates ( 1, 2, 3 ))\n\n    Point3d.placeIn localFrame\n        (Point3d.fromCoordinates ( 3, 3, 3 ))\n    --> Point3d.fromCoordinates ( 4, 5, 6 )\n\n    Point3d.placeIn localFrame\n        (Point3d.fromCoordinates ( 0, -1, -2 ))\n    --> Point3d.fromCoordinates ( 1, 1, 1 )\n\n",
                "type": "Frame3d -> Point3d -> Point3d"
            },
            {
                "name": "projectInto",
                "comment": " Project a point into a given sketch plane. Conceptually, this finds the\n[orthographic projection](https://en.wikipedia.org/wiki/Orthographic_projection)\nof the point onto the plane and then expresses the projected point in 2D sketch\ncoordinates.\n\n    point =\n        Point3d.fromCoordinates ( 2, 1, 3 )\n\n    Point3d.projectInto SketchPlane3d.xy point\n    --> Point2d.fromCoordinates ( 2, 1 )\n\n    Point3d.projectInto SketchPlane3d.yz point\n    --> Point2d.fromCoordinates ( 1, 3 )\n\n    Point3d.projectInto SketchPlane3d.zx point\n    --> Point2d.fromCoordinates ( 3, 2 )\n\n",
                "type": "SketchPlane3d -> Point3d -> Point2d"
            },
            {
                "name": "projectOnto",
                "comment": " Find the [orthographic projection](https://en.wikipedia.org/wiki/Orthographic_projection)\nof a point onto a plane:\n\n    point =\n        Point3d.fromCoordinates ( 1, 2, 3 )\n\n    Point3d.projectOnto Plane3d.xy point\n    --> Point3d.fromCoordinates ( 1, 2, 0 )\n\n    Point3d.projectOnto Plane3d.yz point\n    --> Point3d.fromCoordinates ( 0, 2, 3 )\n\nThe plane does not have to pass through the origin:\n\n    offsetPlane =\n        Plane3d.offsetBy 1 Plane3d.xy\n\n    Point3d.projectOnto offsetPlane point\n    --> Point3d.fromCoordinates ( 1, 2, 1 )\n\n",
                "type": "Plane3d -> Point3d -> Point3d"
            },
            {
                "name": "projectOntoAxis",
                "comment": " Project a point perpendicularly onto an axis.\n\n    point =\n        Point3d.fromCoordinates ( 1, 2, 3 )\n\n    Point3d.projectOntoAxis Axis3d.x\n    --> Point3d.fromCoordinates ( 1, 0, 0 )\n\n    verticalAxis =\n        Axis3d.with\n            { originPoint =\n                Point3d.fromCoordinates ( 0, 1, 2 )\n            , direction = Direction3d.z\n            }\n\n    Point3d.projectOntoAxis verticalAxis\n    --> Point3d.fromCoordinates ( 0, 1, 3 )\n\n",
                "type": "Axis3d -> Point3d -> Point3d"
            },
            {
                "name": "relativeTo",
                "comment": " Take a point defined in global coordinates, and return it expressed in local\ncoordinates relative to a given reference frame.\n\n    localFrame =\n        Frame3d.atPoint\n            (Point3d.fromCoordinates ( 1, 2, 3 ))\n\n    Point3d.relativeTo localFrame\n        (Point3d.fromCoordinates ( 4, 5, 6 ))\n    --> Point3d.fromCoordinates ( 3, 3, 3 )\n\n    Point3d.relativeTo localFrame\n        (Point3d.fromCoordinates ( 1, 1, 1 ))\n    --> Point3d.fromCoordinates ( 0, -1, -2 )\n\n",
                "type": "Frame3d -> Point3d -> Point3d"
            },
            {
                "name": "rotateAround",
                "comment": " Rotate a point around an axis by a given angle (in radians).\n\n    axis =\n        Axis3d.x\n\n    angle =\n        degrees 45\n\n    point =\n        Point3d.fromCoordinates ( 3, 1, 0 )\n\n    Point3d.rotateAround axis angle point\n    --> Point3d.fromCoordinates ( 3, 0.7071, 0.7071 )\n\nRotation direction is given by the right-hand rule, counterclockwise around the\ndirection of the axis.\n\n",
                "type": "Axis3d -> Float -> Point3d -> Point3d"
            },
            {
                "name": "scaleAbout",
                "comment": " Perform a uniform scaling about the given center point. The center point is\ngiven first and the point to transform is given last. Points will contract or\nexpand about the center point by the given scale. Scaling by a factor of 1 is a\nno-op, and scaling by a factor of 0 collapses all points to the center point.\n\n    centerPoint =\n        Point3d.fromCoordinates ( 1, 1, 1 )\n\n    point =\n        Point3d.fromCoordinates ( 1, 2, 3 )\n\n    Point3d.scaleAbout centerPoint 3 point\n    --> Point3d.fromCoordinates ( 1, 4, 7 )\n\n    Point3d.scaleAbout centerPoint 0.5 point\n    --> Point3d.fromCoordinates ( 1, 1.5, 2 )\n\nAvoid scaling by a negative scaling factor - while this may sometimes do what\nyou want it is confusing and error prone. Try a combination of mirror and/or\nrotation operations instead.\n\n",
                "type": "Point3d -> Float -> Point3d -> Point3d"
            },
            {
                "name": "signedDistanceAlong",
                "comment": " Determine how far along an axis a particular point lies. Conceptually, the\npoint is projected perpendicularly onto the axis, and then the distance of this\nprojected point from the axis' origin point is measured. The result will be\npositive if the projected point is ahead the axis' origin point and negative if\nit is behind, with 'ahead' and 'behind' defined by the direction of the axis.\n\n    axis =\n        Axis3d.with\n            { originPoint =\n                Point3d.fromCoordinates ( 1, 0, 0 )\n            , direction = Direction3d.x\n            }\n\n    point =\n        Point3d.fromCoordinates ( 3, 3, 3 )\n\n    Point3d.signedDistanceAlong axis point\n    --> 2\n\n    Point3d.signedDistanceAlong axis Point3d.origin\n    --> -1\n\n",
                "type": "Axis3d -> Point3d -> Float"
            },
            {
                "name": "signedDistanceFrom",
                "comment": " Find the perpendicular distance of a point from a plane. The result will be\npositive if the point is 'above' the plane and negative if it is 'below', with\n'up' defined by the normal direction of the plane.\n\n    plane =\n        Plane3d.with\n            { originPoint =\n                Point3d.fromCoordinates ( 1, 2, 3 )\n            , normalDirection = Direction3d.y\n            }\n\n    point =\n        Point3d.fromCoordinates ( 3, 3, 3 )\n\n    Point3d.signedDistanceFrom plane point\n    --> 1\n\n    Point3d.signedDistanceFrom plane Point3d.origin\n    --> -2\n\nThis means that flipping a plane (reversing its normal direction) will also flip\nthe sign of the result of this function:\n\n    flippedPlane =\n        Plane3d.flip plane\n\n    Point3d.signedDistanceFrom flippedPlane point\n    --> -1\n\n    Point3d.signedDistanceFrom flippedPlane Point3d.origin\n    --> 2\n\n",
                "type": "Plane3d -> Point3d -> Float"
            },
            {
                "name": "squaredDistanceFrom",
                "comment": " Find the square of the distance from one point to another.\n`squaredDistanceFrom` is slightly faster than `distanceFrom`, so for example\n\n    Point3d.squaredDistanceFrom p1 p2\n        > tolerance * tolerance\n\nis equivalent to but slightly more efficient than\n\n    Point3d.distanceFrom p1 p2 > tolerance\n\nsince the latter requires a square root under the hood. In many cases, however,\nthe speed difference will be negligible and using `distanceFrom` is much more\nreadable!\n\n",
                "type": "Point3d -> Point3d -> Float"
            },
            {
                "name": "squaredDistanceFromAxis",
                "comment": " Find the square of the perpendicular distance of a point from an axis. As\nwith `distanceFrom`/`squaredDistanceFrom` this is slightly more efficient than\n`distanceFromAxis` since it avoids a square root.\n",
                "type": "Axis3d -> Point3d -> Float"
            },
            {
                "name": "translateBy",
                "comment": " Translate a point by a given displacement.\n\n    point =\n        Point3d.fromCoordinates ( 3, 4, 5 )\n\n    displacement =\n        Vector3d.fromComponents ( 1, 2, 3 )\n\n    Point3d.translateBy displacement point\n    --> Point3d.fromCoordinates ( 4, 6, 8 )\n\n",
                "type": "Vector3d -> Point3d -> Point3d"
            },
            {
                "name": "xCoordinate",
                "comment": " Get the X coordinate of a point.\n\n    Point3d.fromCoordinates ( 2, 1, 3 )\n        |> Point3d.xCoordinate\n    --> 2\n\n",
                "type": "Point3d -> Float"
            },
            {
                "name": "yCoordinate",
                "comment": " Get the Y coordinate of a point.\n\n    Point3d.fromCoordinates ( 2, 1, 3 )\n        |> Point3d.yCoordinate\n    --> 1\n\n",
                "type": "Point3d -> Float"
            },
            {
                "name": "zCoordinate",
                "comment": " Get the Z coordinate of a point.\n\n    Point3d.fromCoordinates ( 2, 1, 3 )\n        |> Point3d.zCoordinate\n    --> 3\n\n",
                "type": "Point3d -> Float"
            }
        ],
        "binops": []
    },
    {
        "name": "OpenSolid.Axis2d",
        "comment": " <img src=\"https://opensolid.github.io/images/geometry/icons/axis2d.svg\" alt=\"Axis2d\" width=\"160\">\n\nAn `Axis2d` represents an infinitely long straight line in 2D and is defined by\nan origin point and direction. Axes have several uses, such as:\n\n  - Mirroring across the axis\n  - Projecting onto the axis\n  - Measuring distance along the axis\n\n@docs Axis2d\n\n\n# Constants\n\n@docs x, y\n\n\n# Constructors\n\n@docs with\n\n\n# Properties\n\n@docs originPoint, direction\n\n\n# Transformations\n\n@docs flip, moveTo, rotateAround, translateBy, mirrorAcross\n\n\n# Coordinate conversions\n\nFunctions for transforming axes between local and global coordinates in\ndifferent coordinate frames.\n\n@docs relativeTo, placeIn\n\n",
        "unions": [],
        "aliases": [
            {
                "name": "Axis2d",
                "comment": " ",
                "args": [],
                "type": "Axis2d"
            }
        ],
        "values": [
            {
                "name": "direction",
                "comment": " Get the direction of an axis.\n\n    Axis2d.direction exampleAxis\n    --> Direction2d.fromAngle (degrees 30)\n\n",
                "type": "Axis2d -> Direction2d"
            },
            {
                "name": "flip",
                "comment": " Reverse the direction of an axis while keeping the same origin point.\n\n    Axis2d.flip exampleAxis\n    --> Axis2d.with\n    -->     { originPoint =\n    -->         Point2d.fromCoordinates ( 1, 3 )\n    -->     , direction =\n    -->         Direction2d.fromAngle (degrees -150)\n    -->     }\n\n",
                "type": "Axis2d -> Axis2d"
            },
            {
                "name": "mirrorAcross",
                "comment": " Mirror one axis across another. The axis to mirror across is given first and\nthe axis to mirror is given second.\n\n    Axis2d.mirrorAcross Axis2d.x exampleAxis\n    --> Axis2d.with\n    -->     { originPoint =\n    -->         Point2d.fromCoordinates ( 1, -3 )\n    -->     , direction =\n    -->         Direction2d.fromAngle (degrees -30)\n    -->     }\n\n",
                "type": "Axis2d -> Axis2d -> Axis2d"
            },
            {
                "name": "moveTo",
                "comment": " Move an axis so that it has the given origin point but unchanged direction.\n\n    newOrigin =\n        Point2d.fromCoordinates ( 4, 5 )\n\n    Axis2d.moveTo newOrigin exampleAxis\n    --> Axis2d.with\n    -->     { originPoint =\n    -->         Point2d.fromCoordinates ( 4, 5 )\n    -->     , direction =\n    -->         Direction2d.fromAngle (degrees 30)\n    -->     }\n\n",
                "type": "Point2d -> Axis2d -> Axis2d"
            },
            {
                "name": "originPoint",
                "comment": " Get the origin point of an axis.\n\n    Axis2d.originPoint exampleAxis\n    --> Point2d.fromCoordinates ( 1, 3 )\n\n",
                "type": "Axis2d -> Point2d"
            },
            {
                "name": "placeIn",
                "comment": " Take an axis defined in local coordinates relative to a given reference\nframe, and return that axis expressed in global coordinates.\n\n    frame =\n        Frame2d.atPoint (Point2d.fromCoordinates ( 2, 3 ))\n\n    Axis2d.placeIn frame exampleAxis\n    --> Axis2d.with\n    -->     { originPoint =\n    -->         Point2d.fromCoordinates ( 3, 6 )\n    -->     , direction =\n    -->         Direction2d.fromAngle (degrees 30)\n    -->     }\n\n",
                "type": "Frame2d -> Axis2d -> Axis2d"
            },
            {
                "name": "relativeTo",
                "comment": " Take an axis defined in global coordinates, and return it expressed in local\ncoordinates relative to a given reference frame.\n\n    frame =\n        Frame2d.atPoint (Point2d.fromCoordinates ( 2, 3 ))\n\n    Axis2d.relativeTo frame exampleAxis\n    --> Axis2d.with\n    -->     { originPoint =\n    -->         Point2d.fromCoordinates ( -1, 0 )\n    -->     , direction =\n    -->         Direction2d.fromAngle (degrees 30)\n    -->     }\n\n",
                "type": "Frame2d -> Axis2d -> Axis2d"
            },
            {
                "name": "rotateAround",
                "comment": " Rotate an axis around a given center point by a given angle. Rotates the\naxis' origin point around the given point by the given angle and the axis'\ndirection by the given angle.\n\n    Axis2d.rotateAround Point2d.origin\n        (degrees 90)\n        exampleAxis\n    --> Axis2d.with\n    -->     { originPoint =\n    -->         Point2d.fromCoordinates ( -3, 1 )\n    -->     , direction =\n    -->         Direction2d.fromAngle (degrees 120)\n    -->     }\n\n",
                "type": "Point2d -> Float -> Axis2d -> Axis2d"
            },
            {
                "name": "translateBy",
                "comment": " Translate an axis by a given displacement. Applies the given displacement to\nthe axis' origin point and leaves the direction unchanged.\n\n    displacement =\n        Vector2d.fromComponents ( 2, 3 )\n\n    Axis2d.translateBy displacement exampleAxis\n    --> Axis2d.with\n    -->     { originPoint =\n    -->         Point2d.fromCoordinates ( 3, 6 )\n    -->     , direction =\n    -->         Direction2d.fromAngle (degrees 30)\n    -->     }\n\n",
                "type": "Vector2d -> Axis2d -> Axis2d"
            },
            {
                "name": "with",
                "comment": " Construct an axis from its origin point and direction:\n\n    exampleAxis =\n        Axis2d.with\n            { originPoint =\n                Point2d.fromCoordinates ( 1, 3 )\n            , direction =\n                Direction2d.fromAngle (degrees 30)\n            }\n\n",
                "type": "{ originPoint : Point2d, direction : Direction2d } -> Axis2d"
            },
            {
                "name": "x",
                "comment": " The global X axis.\n\n    Axis2d.x\n    --> Axis2d.with\n    -->     { originPoint = Point2d.origin\n    -->     , direction = Direction2d.x\n    -->     }\n\n",
                "type": "Axis2d"
            },
            {
                "name": "y",
                "comment": " The global Y axis.\n\n    Axis2d.y\n    --> Axis2d.with\n    -->     { originPoint = Point2d.origin\n    -->     , direction = Direction2d.y\n    -->     }\n\n",
                "type": "Axis2d"
            }
        ],
        "binops": []
    },
    {
        "name": "OpenSolid.BoundingBox3d",
        "comment": " <img src=\"https://opensolid.github.io/images/geometry/icons/boundingBox3d.svg\" alt=\"BoundingBox3d\" width=\"160\">\n\nA `BoundingBox3d` is a rectangular box in 3D defined by its minimum and maximum\nX, Y and Z values. It is possible to generate bounding boxes for most geometric\nobjects; for example, [`Triangle3d.boundingBox`](OpenSolid-Triangle3d#boundingBox)\ntakes a `Triangle3d` and returns a `BoundingBox3d` that contains that triangle.\nThere are several use cases where it is more efficient to deal with the bounding\nbox of an object than the object itself, such as:\n\n  - Intersection checking: If (for example) the bounding boxes of a line segment\n    and a triangle do not overlap, then the line segment and triangle cannot\n    possibly intersect each other. Expensive intersection checking therefore\n    only has to be performed for line segments and triangles whose bounding\n    boxes _do_ overlap.\n  - 3D rendering: When rendering a 3D scene, any object whose bounding box is\n    not visible must itself be not visible, and therefore does not have to be\n    drawn. This provides a simple form of culling.\n\n@docs BoundingBox3d\n\n\n# Constructors\n\n@docs with, singleton, hull, intersection, hullOf\n\n\n# Properties\n\n@docs extrema, minX, maxX, minY, maxY, minZ, maxZ, dimensions, midX, midY, midZ, centroid\n\n\n# Queries\n\n@docs contains, isContainedIn, intersects, overlaps, overlappingBy, separatedBy\n\n\n# Transformations\n\n@docs scaleAbout, translateBy\n\n",
        "unions": [],
        "aliases": [
            {
                "name": "BoundingBox3d",
                "comment": " ",
                "args": [],
                "type": "BoundingBox3d"
            }
        ],
        "values": [
            {
                "name": "centroid",
                "comment": " Get the point at the center of a bounding box.\n\n    BoundingBox3d.centroid exampleBox\n    --> Point3d.fromCoordinates ( 0, 3.5, 3.5 )\n\n",
                "type": "BoundingBox3d -> Point3d"
            },
            {
                "name": "contains",
                "comment": " Check if a bounding box contains a particular point.\n\n    firstPoint =\n        Point3d.fromCoordinates ( 1, 4, 3 )\n\n    secondPoint =\n        Point3d.fromCoordinates ( 3, 4, 5 )\n\n    BoundingBox3d.contains firstPoint exampleBox\n    --> True\n\n    BoundingBox3d.contains secondPoint exampleBox\n    --> False\n\n",
                "type": "Point3d -> BoundingBox3d -> Bool"
            },
            {
                "name": "dimensions",
                "comment": " Get the X, Y and Z dimensions (widths) of a bounding box.\n\n    BoundingBox3d.dimensions exampleBox\n    --> ( 4, 3, 1 )\n\n",
                "type": "BoundingBox3d -> ( Float, Float, Float )"
            },
            {
                "name": "extrema",
                "comment": " Get the minimum and maximum X, Y and Z values of a bounding box in a single\nrecord.\n\n    BoundingBox3d.extrema exampleBox\n    --> { minX = -2\n    --> , maxX = 2\n    --> , minY = 2\n    --> , maxY = 5\n    --> , minZ = 3\n    --> , maxZ = 4\n    --> }\n\nCan be useful when combined with record destructuring, for example\n\n    { minX, maxX, minY, maxY, minZ, maxZ } =\n        BoundingBox3d.extrema exampleBox\n\n\n    --> minX = -2\n    --> maxX = 2\n    --> minY = 2\n    --> maxY = 5\n    --> minZ = 3\n    --> maxZ = 4\n\n",
                "type": "BoundingBox3d -> { minX : Float, maxX : Float, minY : Float, maxY : Float, minZ : Float, maxZ : Float }"
            },
            {
                "name": "hull",
                "comment": " Build a bounding box that contains both given bounding boxes.\n\n    firstBox =\n        BoundingBox3d.with\n            { minX = 1\n            , maxX = 4\n            , minY = 2\n            , maxY = 3\n            , minZ = 0\n            , maxZ = 5\n            }\n\n    secondBox =\n        BoundingBox3d.with\n            { minX = -2\n            , maxX = 2\n            , minY = 4\n            , maxY = 5\n            , minZ = -1\n            , maxZ = 0\n            }\n\n    BoundingBox3d.hull firstBox secondBox\n    --> BoundingBox3d.with\n    -->     { minX = -2\n    -->     , maxX = 4\n    -->     , minY = 2\n    -->     , maxY = 5\n    -->     , minZ = -1\n    -->     , maxZ = 5\n    -->     }\n\n",
                "type": "BoundingBox3d -> BoundingBox3d -> BoundingBox3d"
            },
            {
                "name": "hullOf",
                "comment": " Construct a bounding box containing all bounding boxes in the given list. If\nthe list is empty, returns `Nothing`.\n\n    singletonBox =\n        BoundingBox3d.singleton\n            (Point3d.fromCoordinates ( 2, 1, 0 ))\n\n    BoundingBox3d.hullOf [ exampleBox, singletonBox ]\n    --> Just\n    -->     (BoundingBox3d.with\n    -->         { minX = -2,\n    -->         , maxX = 2\n    -->         , minY = 1\n    -->         , maxY = 5\n    -->         , minZ = 0\n    -->         , maxZ = 4\n    -->         }\n    -->     )\n\n    BoundingBox3d.hullOf [ exampleBox ]\n    --> Just exampleBox\n\n    BoundingBox3d.hullOf []\n    --> Nothing\n\nIf you have exactly two bounding boxes, you can use [`BoundingBox3d.hull`](#hull)\ninstead (which returns a `BoundingBox3d` instead of a `Maybe BoundingBox3d`).\n\n",
                "type": "List BoundingBox3d -> Maybe BoundingBox3d"
            },
            {
                "name": "intersection",
                "comment": " Attempt to build a bounding box that contains all points common to both\ngiven bounding boxes. If the given boxes do not overlap, returns `Nothing`.\n\n    firstBox =\n        BoundingBox3d.with\n            { minX = 1\n            , maxX = 4\n            , minY = 2\n            , maxY = 3\n            , minZ = 5\n            , maxZ = 8\n            }\n\n    secondBox =\n        BoundingBox3d.with\n            { minX = 2\n            , maxX = 5\n            , minY = 1\n            , maxY = 4\n            , minZ = 6\n            , maxZ = 7\n            }\n\n    thirdBox =\n        BoundingBox3d.with\n            { minX = 1\n            , maxX = 4\n            , minY = 4\n            , maxY = 5\n            , minZ = 5\n            , maxZ = 8\n            }\n\n    BoundingBox3d.intersection firstBox secondBox\n    --> Just\n    -->     (BoundingBox3d.with\n    -->         { minX = 2\n    -->         , maxX = 4\n    -->         , minY = 2\n    -->         , maxY = 3\n    -->         , minZ = 6\n    -->         , maxZ = 7\n    -->         }\n    -->     )\n\n    BoundingBox3d.intersection firstBox thirdBox\n    --> Nothing\n\n",
                "type": "BoundingBox3d -> BoundingBox3d -> Maybe BoundingBox3d"
            },
            {
                "name": "intersects",
                "comment": " Test if two boxes touch or overlap at all (have any points in common);\n\n    BoundingBox3d.intersects firstBox secondBox\n\nis equivalent to\n\n    BoundingBox3d.intersection firstBox secondBox\n        /= Nothing\n\nbut is more efficient.\n\n    firstBox =\n        BoundingBox3d.with\n            { minX = 0\n            , maxX = 3\n            , minY = 0\n            , maxY = 2\n            , minZ = 0\n            , maxZ = 1\n            }\n\n    secondBox =\n        BoundingBox3d.with\n            { minX = 0\n            , maxX = 3\n            , minY = 1\n            , maxY = 4\n            , minZ = -1\n            , maxZ = 2\n            }\n\n    thirdBox =\n        BoundingBox3d.with\n            { minX = 0\n            , maxX = 3\n            , minY = 4\n            , maxY = 5\n            , minZ = -1\n            , maxZ = 2\n            }\n\n    BoundingBox3d.intersects firstBox secondBox\n    --> True\n\n    BoundingBox3d.intersects firstBox thirdBox\n    --> False\n\n",
                "type": "BoundingBox3d -> BoundingBox3d -> Bool"
            },
            {
                "name": "isContainedIn",
                "comment": " Test if the second given bounding box is fully contained within the first\n(is a subset of it).\n\n    outerBox =\n        BoundingBox3d.with\n            { minX = 0\n            , maxX = 10\n            , minY = 0\n            , maxY = 10\n            , minZ = 0\n            , maxZ = 10\n            }\n\n    innerBox =\n        BoundingBox3d.with\n            { minX = 1\n            , maxX = 5\n            , minY = 3\n            , maxY = 9\n            , minZ = 7\n            , maxZ = 8\n            }\n\n    overlappingBox =\n        BoundingBox3d.with\n            { minX = 1\n            , maxX = 5\n            , minY = 3\n            , maxY = 12\n            , minZ = 7\n            , maxZ = 8\n            }\n\n    BoundingBox3d.isContainedIn outerBox innerBox\n    --> True\n\n    BoundingBox3d.isContainedIn outerBox overlappingBox\n    --> False\n\n",
                "type": "BoundingBox3d -> BoundingBox3d -> Bool"
            },
            {
                "name": "maxX",
                "comment": " Get the maximum X value of a bounding box.\n\n    BoundingBox3d.maxX exampleBox\n    --> 2\n\n",
                "type": "BoundingBox3d -> Float"
            },
            {
                "name": "maxY",
                "comment": " Get the maximum Y value of a bounding box.\n\n    BoundingBox3d.maxY exampleBox\n    --> 5\n\n",
                "type": "BoundingBox3d -> Float"
            },
            {
                "name": "maxZ",
                "comment": " Get the maximum Z value of a bounding box.\n\n    BoundingBox3d.maxZ exampleBox\n    --> 4\n\n",
                "type": "BoundingBox3d -> Float"
            },
            {
                "name": "midX",
                "comment": " Get the median X value of a bounding box.\n\n    BoundingBox3d.midX exampleBox\n    --> 0\n\n",
                "type": "BoundingBox3d -> Float"
            },
            {
                "name": "midY",
                "comment": " Get the median Y value of a bounding box.\n\n    BoundingBox3d.midY exampleBox\n    --> 3.5\n\n",
                "type": "BoundingBox3d -> Float"
            },
            {
                "name": "midZ",
                "comment": " Get the median Z value of a bounding box.\n\n    BoundingBox3d.midZ exampleBox\n    --> 3.5\n\n",
                "type": "BoundingBox3d -> Float"
            },
            {
                "name": "minX",
                "comment": " Get the minimum X value of a bounding box.\n\n    BoundingBox3d.minX exampleBox\n    --> -2\n\n",
                "type": "BoundingBox3d -> Float"
            },
            {
                "name": "minY",
                "comment": " Get the minimum Y value of a bounding box.\n\n    BoundingBox3d.minY exampleBox\n    --> 2\n\n",
                "type": "BoundingBox3d -> Float"
            },
            {
                "name": "minZ",
                "comment": " Get the minimum Z value of a bounding box.\n\n    BoundingBox3d.minZ exampleBox\n    --> 3\n\n",
                "type": "BoundingBox3d -> Float"
            },
            {
                "name": "overlappingBy",
                "comment": " Check if one box overlaps another by less than, greater than or equal to a\ngiven amount. For example, you could perform a tolerant collision check (one\nthat only returns true if the boxes overlap by at least some small finite\namount, and ignores boxes that just barely touch each other) as\n\n    boxesCollide =\n        BoundingBox3d.overlappingBy GT 0.001 box1 box2\n\nThis can be read as \"`box1` and `box2` are overlapping by greater than 0.001\nunits\". (The [`Order`](http://package.elm-lang.org/packages/elm-lang/core/latest/Basics#Order)\ntype and its three values `LT`, `GT` and `EQ` are defined in Elm's `Basics`\nmodule so are available by default in any Elm program.)\n\nOverlap is defined as the _minimum_ distance one box would have to move so that\nit did not touch the other, and is always positive for any two overlapping\nboxes.\n\nBoxes that just touch are considered to have an overlap of zero, which is\ndistinct from 'no overlap'. Boxes that do not touch or overlap at all are\nconsidered to have an overlap which is less than zero but not comparable to any\nnegative number.\n\n\n### Less than\n\n  - `overlappingBy LT 1e-3` will return true if the two boxes overlap by less\n    than 0.001 units or if they do not overlap at all (false if they overlap by\n    more than 0.001 units).\n  - `overlappingBy LT 0` will return true only if the two boxes don't touch or\n    overlap at all.\n  - `overlappingBy LT -1e-3` will always return false! If you care about _how\n    much_ two boxes are separated by, use `separatedBy` instead.\n\n\n### Greater than\n\n  - `overlappingBy GT 1e-3` will return true if the two boxes overlap by at\n    least 0.001 units (false if they overlap by less than that or do not overlap\n    at all).\n  - `overlappingBy GT 0` will return true if the two boxes overlap by any\n    non-zero amount (false if they just touch or do not overlap at all).\n  - `overlappingBy GT -1e-3` doesn't make a lot of sense but will return true if\n    the boxes touch or overlap at all (false if they don't overlap, regardless\n    of how close they are to overlapping). In this case, though, it would make\n    more sense to just user `intersects` instead.\n\n\n### Equal to\n\nChecking whether two boxes overlap by exactly a given amount is pretty weird and\nvulnerable to floating-point roundoff, but is defined as follows:\n\n  - `overlappingBy EQ 1e-3` will return true if the two boxes overlap by exactly\n    0.001 units.\n  - `overlappingBy EQ 0` will return true if and only if the boxes just touch\n    each other.\n  - `overlappingBy EQ -1e-3` will always return false.\n\n",
                "type": "Order -> Float -> BoundingBox3d -> BoundingBox3d -> Bool"
            },
            {
                "name": "overlaps",
                "comment": " DEPRECATED: Alias for `intersects`, kept for compatibility. Use `intersects`\ninstead.\n",
                "type": "BoundingBox3d -> BoundingBox3d -> Bool"
            },
            {
                "name": "scaleAbout",
                "comment": " Scale a bounding box about a given point by a given scale.\n\n    point =\n        Point3d.fromCoordinates ( 2, 2, 2 )\n\n    BoundingBox3d.scaleAbout point 2 exampleBox\n    --> BoundingBox3d.with\n    -->     { minX = -6\n    -->     , maxX = 2\n    -->     , minY = 2\n    -->     , maxY = 8\n    -->     , minZ = 4\n    -->     , maxZ = 6\n    -->     }\n\n",
                "type": "Point3d -> Float -> BoundingBox3d -> BoundingBox3d"
            },
            {
                "name": "separatedBy",
                "comment": " Check if one box is separated from another by less than, greater than or\nequal to a given amount. For example, to perform clash detection between some\nobjects, you could use `separatedBy` on those objects' bounding boxes as a quick\ncheck to see if the objects had a gap of at least 1 cm between them:\n\n    safelySeparated =\n        BoundingBox3d.separatedBy GT 0.01 box1 box2\n\nThis can be read as \"`box1` and `box2` are separated by greater than 0.01\nunits\". (The [`Order`](http://package.elm-lang.org/packages/elm-lang/core/latest/Basics#Order)\ntype and its three values `LT`, `GT` and `EQ` are defined in Elm's `Basics`\nmodule so are available by default in any Elm program.)\n\nSeparation is defined as the _minimum_ distance one box would have to move\nso that it touched the other, and is always positive for any two boxes that do\nnot touch.\n\nBoxes that just touch are considered to have a separation of zero, which is\ndistinct from 'no separation'. 'No separation' (overlap) is considered to be\nless than zero but not comparable to any negative number.\n\n\n### Less than\n\n  - `separatedBy LT 1e-3` will return true if the two boxes are separated by\n    less than 0.001 units or if they touch or overlap (false if they are\n    separated by at least 0.001 units).\n  - `separatedBy LT 0` will return true only if the boxes overlap by some\n    non-zero amount.\n  - `separatedBy LT -1e-3` will always return false! If you care about _how\n    much_ two boxes overlap by, use `overlappingBy` instead.\n\n\n### Greater than\n\n  - `separatedBy GT 1e-3` will return true if the two boxes are separated by at\n    least 0.001 units (false if they are separated by less than that or if they\n    touch or overlap).\n  - `separatedBy GT 0` will return true if the two boxes are separated by any\n    non-zero amount (false if they touch or overlap).\n  - `separatedBy GT -1e-3` doesn't make a lot of sense but will return true if\n    the boxes just touch or are separated by any amount (false if they overlap\n    by any non-zero amount).\n\n\n### Equal to\n\nChecking whether two boxes are separated by exactly a given amount is pretty\nweird and vulnerable to floating-point roundoff, but is defined as follows:\n\n  - `separatedBy EQ 1e-3` will return true if the two boxes are separated by\n    exactly 0.001 units.\n  - `separatedBy EQ 0` will return true if and only if the boxes just touch each\n    other.\n  - `separatedBy EQ -3` will always return false.\n\n",
                "type": "Order -> Float -> BoundingBox3d -> BoundingBox3d -> Bool"
            },
            {
                "name": "singleton",
                "comment": " Construct a zero-width bounding box containing a single point.\n\n    point =\n        Point3d.fromCoordinates ( 2, 1, 3 )\n\n    BoundingBox3d.singleton point\n    --> BoundingBox3d.with\n    -->     { minX = 2\n    -->     , maxX = 2\n    -->     , minY = 1\n    -->     , maxY = 1\n    -->     , minZ = 3\n    -->     , maxZ = 3\n    -->     }\n\n",
                "type": "Point3d -> BoundingBox3d"
            },
            {
                "name": "translateBy",
                "comment": " Translate a bounding box by a given displacement.\n\n    displacement =\n        Vector3d.fromComponents ( 2, -3, 1 )\n\n    BoundingBox3d.translateBy displacement exampleBox\n    --> BoundingBox3d.with\n    -->     { minX = 0\n    -->     , maxX = 4\n    -->     , minY = -1\n    -->     , maxY = 2\n    -->     , minZ = 4\n    -->     , maxZ = 5\n    -->     }\n\n",
                "type": "Vector3d -> BoundingBox3d -> BoundingBox3d"
            },
            {
                "name": "with",
                "comment": " Construct a bounding box from its minimum and maximum X, Y and Z values:\n\n    exampleBox =\n        BoundingBox3d.with\n            { minX = -2\n            , maxX = 2\n            , minY = 2\n            , maxY = 5\n            , minZ = 3\n            , maxZ = 4\n            }\n\nIf the minimum and maximum values are provided in the wrong order (for example\nif <code>minX&nbsp;>&nbsp;maxX</code>), then they will be swapped so that the\nresulting bounding box is valid.\n\n",
                "type": "{ minX : Float, maxX : Float, minY : Float, maxY : Float, minZ : Float, maxZ : Float } -> BoundingBox3d"
            }
        ],
        "binops": []
    },
    {
        "name": "OpenSolid.Direction3d",
        "comment": " <img src=\"https://opensolid.github.io/images/geometry/icons/direction3d.svg\" alt=\"Direction3d\" width=\"160\">\n\nA `Direction3d` represents a direction like 'up' or 'north' or 'forwards'. They\nare represented using X, Y and Z components, and can be converted to vectors if\nnecessary, but should be thought of as conceptually different. Directions have\nseveral uses, such as:\n\n  - Constructing a vector from a length and direction\n  - Determining the component of a vector in a particular direction (for\n    example, finding the component of velocity in the up direction to get\n    vertical speed)\n  - Determining the angle between two directions\n  - Defining the orientation of an axis, plane or reference frame\n\n@docs Direction3d\n\n\n# Constants\n\n@docs x, y, z, positiveX, negativeX, positiveY, negativeY, positiveZ, negativeZ\n\n\n# Constructors\n\n@docs with, from, on, perpendicularTo, perpendicularBasis, orthonormalize, orthogonalize, unsafe\n\n\n# Properties\n\n@docs components, xComponent, yComponent, zComponent, azimuth, elevation\n\n\n# Comparison\n\n@docs equalWithin\n\n\n# Measurement\n\n@docs componentIn, angleFrom\n\n\n# Conversion\n\n@docs toVector\n\n\n# Transformations\n\n@docs flip, rotateAround, mirrorAcross, projectOnto\n\n\n# Coordinate conversions\n\nFunctions for transforming directions between local and global coordinates in\ndifferent coordinate frames. Like other transformations, coordinate\ntransformations of directions depend only on the orientations of the relevant\nframes, not their positions.\n\nFor the examples, assume the following definition of a local coordinate frame,\none that is rotated 30 degrees counterclockwise around the Z axis from the\nglobal XYZ frame:\n\n    rotatedFrame =\n        Frame3d.xyz\n            |> Frame3d.rotateAround Axis3d.z (degrees 30)\n\n@docs relativeTo, placeIn, projectInto\n\n",
        "unions": [],
        "aliases": [
            {
                "name": "Direction3d",
                "comment": " ",
                "args": [],
                "type": "Direction3d"
            }
        ],
        "values": [
            {
                "name": "angleFrom",
                "comment": " Find the angle from one direction to another. The result will be in the\nrange 0 to π.\n\n    Direction3d.angleFrom Direction3d.x Direction3d.x\n    --> degrees 0\n\n    Direction3d.angleFrom Direction3d.x Direction3d.z\n    --> degrees 90\n\n    Direction3d.angleFrom\n        Direction3d.y\n        Direction3d.negativeY\n    --> degrees 180\n\n",
                "type": "Direction3d -> Direction3d -> Float"
            },
            {
                "name": "azimuth",
                "comment": " Get the angle of a direction in the XY plane, measured from the X axis\ntowards the Y axis (counterclockwise around the Z axis). The result will be in\nthe range -π to π.\n\n    Direction3d.azimuth Direction3d.x\n    --> 0\n\n    Direction3d.azimuth Direction3d.y\n    --> degrees 90\n\n    Direction3d.azimuth Direction3d.negativeY\n    --> degrees -90\n\n    Direction3d.azimuth Direction3d.negativeX\n    --> degrees 180\n\nVertical directions are considered to have an azimuth of zero:\n\n    Direction3d.azimuth Direction3d.z\n    --> 0\n\n",
                "type": "Direction3d -> Float"
            },
            {
                "name": "componentIn",
                "comment": " Find the component of one direction in another direction. This is equal to\nthe cosine of the angle between the directions, or equivalently the dot product\nof the two directions converted to unit vectors.\n\n    direction =\n        Direction3d.with\n            { azimuth = 0\n            , elevation = degrees 60\n            }\n\n    Direction3d.componentIn Direction3d.x direction\n    --> 0.5\n\n    Direction3d.componentIn Direction3d.z direction\n    --> 0.866\n\n    Direction3d.componentIn direction direction\n    --> 1\n\n    direction\n        |> Direction3d.componentIn\n            (Direction3d.flip direction)\n    --> -1\n\nThis is more general and flexible than using `xComponent`, `yComponent` or\n`zComponent`, all of which can be expressed in terms of `componentIn`; for\nexample,\n\n    Direction3d.zComponent direction\n\nis equivalent to\n\n    Direction3d.componentIn Direction3d.z direction\n\n",
                "type": "Direction3d -> Direction3d -> Float"
            },
            {
                "name": "components",
                "comment": " Get the components of a direction as a tuple (the components it would have\nas a unit vector, also know as its direction cosines).\n\n    ( x, y, z ) =\n        Direction3d.components direction\n\n",
                "type": "Direction3d -> ( Float, Float, Float )"
            },
            {
                "name": "elevation",
                "comment": " Get the angle of a direction from the XY plane towards positive Z. The\nresult will be in the range -π/2 to π/2.\n\n    Direction3d.elevation Direction3d.x\n    --> 0\n\n    Direction3d.elevation Direction3d.negativeY\n    --> 0\n\n    Direction3d.elevation Direction3d.z\n    --> degrees 90\n\n    Direction3d.elevation Direction3d.negativeZ\n    --> degrees -90\n\n",
                "type": "Direction3d -> Float"
            },
            {
                "name": "equalWithin",
                "comment": " Compare two directions within an angular tolerance. Returns true if the\nangle between the two given directions is less than the given tolerance.\n\n    rotatedDirection =\n        Direction3d.x\n            |> Direction3d.rotateAround Axis3d.z\n                (degrees 2)\n\n    Direction3d.equalWithin (degrees 5)\n        Direction3d.x\n        rotatedDirection\n    --> True\n\n    Direction3d.equalWithin (degrees 1)\n        Direction3d.x\n        rotatedDirection\n    --> False\n\n",
                "type": "Float -> Direction3d -> Direction3d -> Bool"
            },
            {
                "name": "flip",
                "comment": " Reverse a direction.\n\n    Direction3d.flip Direction3d.y\n    --> Direction3d.negativeY\n\n",
                "type": "Direction3d -> Direction3d"
            },
            {
                "name": "from",
                "comment": " Attempt to construct the direction from the first given point to the second.\nIf the two points are coincident, returns `Nothing`.\n\n    point =\n        Point3d.fromCoordinates ( 1, 0, 1 )\n\n    Direction3d.from Point3d.origin point\n    --> Just\n    -->     (Direction3d.with\n    -->         { azimuth = 0\n    -->         , elevation = degrees 45\n    -->         }\n    -->     )\n\n    Direction3d.from point Point3d.origin\n    --> Just\n    -->     (Direction3d.with\n    -->         { azimuth = degrees 180\n    -->         , elevation = degrees -45\n    -->         }\n    -->     )\n\n    Direction3d.from point point\n    --> Nothing\n\n",
                "type": "Point3d -> Point3d -> Maybe Direction3d"
            },
            {
                "name": "mirrorAcross",
                "comment": " Mirror a direction across a plane.\n\n    direction =\n        Direction3d.with\n            { azimuth = degrees 30\n            , elevation = degrees 60\n            }\n\n    Direction3d.mirrorAcross Plane3d.xy direction\n    --> Direction3d.with\n    -->     { azimuth = degrees 30\n    -->     , elevation = degrees -60\n    -->     }\n\nNote that only the normal direction of the plane affects the result, not the\nposition of its origin point, since directions are position-independent:\n\n    Direction3d.mirrorAcross Plane3d.yz direction\n    --> Direction3d.with\n    -->     { azimuth = degrees 150\n    -->     , elevation = degrees 60\n    -->     }\n\n    offsetPlane =\n        Plane3d.offsetBy 10 Plane3d.yz\n\n    Direction3d.mirrorAcross offsetPlane direction\n    --> Direction3d.with\n    -->     { azimuth = degrees 150\n    -->     , elevation = degrees 60\n    -->     }\n\n",
                "type": "Plane3d -> Direction3d -> Direction3d"
            },
            {
                "name": "negativeX",
                "comment": " The negative X direction.\n\n    Direction3d.components Direction3d.negativeX\n    --> ( -1, 0, 0 )\n\n",
                "type": "Direction3d"
            },
            {
                "name": "negativeY",
                "comment": " The negative Y direction.\n\n    Direction3d.components Direction3d.negativeY\n    --> ( 0, -1, 0 )\n\n",
                "type": "Direction3d"
            },
            {
                "name": "negativeZ",
                "comment": " The negative Z direction.\n\n    Direction3d.components Direction3d.negativeZ\n    --> ( 0, 0, -1 )\n\n",
                "type": "Direction3d"
            },
            {
                "name": "on",
                "comment": " Construct a 3D direction lying _on_ a sketch plane by providing a 2D\ndirection specified in XY coordinates _within_ the sketch plane.\n\n    horizontalDirection =\n        Direction3d.on SketchPlane3d.xy <|\n            Direction2d.fromAngle (degrees 45)\n\n    Direction3d.components horizontalDirection\n    --> ( 0.7071, 0.7071, 0 )\n\n    thirtyDegreesFromZ =\n        Direction3d.on SketchPlane3d.zx <|\n            Direction2d.fromAngle (degrees 30)\n\n    Direction3d.components thirtyDegreesFromZ\n    --> ( 0.5, 0, 0.866 )\n\n",
                "type": "SketchPlane3d -> Direction2d -> Direction3d"
            },
            {
                "name": "orthogonalize",
                "comment": " Attempt to form a set of three mutually perpendicular directions from the\nthree given directions;\n\n    Direction3d.orthogonalize\n        ( xDirection\n        , yDirection\n        , zDirection\n        )\n\nis equivalent to\n\n    Direction3d.orthonormalize\n        ( Direction3d.toVector xDirection\n        , Direction3d.toVector yDirection\n        , Direction3d.toVector zDirection\n        )\n\n",
                "type": "( Direction3d, Direction3d, Direction3d ) -> Maybe ( Direction3d, Direction3d, Direction3d )"
            },
            {
                "name": "orthonormalize",
                "comment": " Attempt to form a set of three mutually perpendicular directions from the\nthree given vectors by performing [Gram-Schmidt normalization](https://en.wikipedia.org/wiki/Gram%E2%80%93Schmidt_process):\n\n  - The first returned direction will be equal to the direction of the first\n    given vector\n  - The second returned direction will be as close as possible to the second\n    given vector while being perpendicular to the first returned direction\n  - The third returned direction will be as close as possible to the third given\n    vector while being perpendicular to the first and second returned directions\n\nIf any of the given vectors are zero, any two of them are parallel, or the three\nare coplanar, `Nothing` will be returned.\n\n    Direction3d.orthonormalize\n        ( Vector3d.fromComponents ( 3, 3, 0 )\n        , Vector3d.fromComponents ( 0, 2, 0 )\n        , Vector3d.fromComponents ( 1, 2, 3 )\n        )\n    --> Just\n    -->     ( Direction3d.with\n    -->         { azimuth = degrees 45\n    -->         , elevation = 0\n    -->         }\n    -->     , Direction3d.with\n    -->         { azimuth = degrees 135\n    -->         , elevation = 0\n    -->         }\n    -->     , Direction3d.positiveZ\n    -->     )\n\n    -- Three vectors in the XY plane:\n    Direction3d.orthonormalize\n        ( Vector3d.fromComponents ( 2, 0, 0 )\n        , Vector3d.fromComponents ( 3, 1, 0 )\n        , Vector3d.fromComponents ( 4, 2, 0 )\n        )\n    --> Nothing\n\n",
                "type": "( Vector3d, Vector3d, Vector3d ) -> Maybe ( Direction3d, Direction3d, Direction3d )"
            },
            {
                "name": "perpendicularBasis",
                "comment": " Construct a pair of directions that are perpendicular to each other and both\nperpendicular to the given direction.\n\nThe given direction and the two returned directions will form a\n[right-handed](https://en.wikipedia.org/wiki/Cartesian_coordinate_system#Orientation_and_handedness)\nsystem (that is, a right-handed `Frame3d` could be constructed by using the\ngiven direction as the X direction and the two returned directions as the Y and\nZ directions, or the given direction as the Z direction and the two returned\ndirections as the X and Y directions).\n\n    Direction3d.perpendicularBasis Direction3d.x\n    --> ( Direction3d.negativeZ\n    --> , Direction3d.positiveY\n    --> )\n\n    Direction3d.perpendicularBasis Direction3d.y\n    --> ( Direction3d.positiveZ\n    --> , Direction3d.positiveX\n    --> )\n\n",
                "type": "Direction3d -> ( Direction3d, Direction3d )"
            },
            {
                "name": "perpendicularTo",
                "comment": " Construct an arbitrary direction perpendicular to the given direction. The\nexact resulting direction is not specified, but it is guaranteed to be\nperpendicular to the given direction.\n\n    Direction3d.perpendicularTo Direction3d.x\n    --> Direction3d.negativeZ\n\n    Direction3d.perpendicularTo Direction3d.y\n    --> Direction3d.positiveZ\n\n    direction =\n        Direction3d.with\n            { azimuth = 0\n            , elevation = degrees 60\n            }\n\n    Direction3d.perpendicularTo direction\n    --> Direction3d.with\n    -->     { azimuth = 0\n    -->     , elevation = degrees -30\n    -->     }\n\n",
                "type": "Direction3d -> Direction3d"
            },
            {
                "name": "placeIn",
                "comment": " Take a direction defined in local coordinates relative to a given reference\nframe, and return that direction expressed in global coordinates.\n\n    Direction3d.placeIn rotatedFrame Direction3d.x\n    --> Direction3d.with\n    -->     { azimuth = degrees 30\n    -->     , elevation = 0\n    -->     }\n\n    Direction3d.placeIn rotatedFrame Direction3d.y\n    --> Direction3d.with\n    -->     { azimuth = degrees 120\n    -->     , elevation = 0\n    -->     }\n\n    Direction3d.placeIn rotatedFrame Direction3d.z\n    --> Direction3d.z\n\n",
                "type": "Frame3d -> Direction3d -> Direction3d"
            },
            {
                "name": "positiveX",
                "comment": " The positive X direction.\n\n    Direction3d.components Direction3d.positiveX\n    --> ( 1, 0, 0 )\n\n",
                "type": "Direction3d"
            },
            {
                "name": "positiveY",
                "comment": " The positive Y direction.\n\n    Direction3d.components Direction3d.positiveY\n    --> ( 0, 1, 0 )\n\n",
                "type": "Direction3d"
            },
            {
                "name": "positiveZ",
                "comment": " The positive Z direction.\n\n    Direction3d.components Direction3d.positiveZ\n    --> ( 0, 0, 1 )\n\n",
                "type": "Direction3d"
            },
            {
                "name": "projectInto",
                "comment": " Project a direction into a given sketch plane. Conceptually, this finds the\n[orthographic projection](https://en.wikipedia.org/wiki/Orthographic_projection)\nof the direction onto the plane, re-normalizes it to have unit length, and then\nexpresses the projected direction in 2D sketch coordinates.\n\nThis is only possible if the direction is not perpendicular to the sketch\nplane; if it is perpendicular, `Nothing` is returned.\n\n    direction =\n        Direction3d.with\n            { azimuth = degrees -60\n            , elevation = 0\n            }\n\n    Direction3d.projectInto SketchPlane3d.xy direction\n    --> Just (Direction2d.fromAngle (degrees -60))\n\n    Direction3d.projectInto SketchPlane3d.xz direction\n    --> Just Direction2d.x\n\n    Direction3d.projectInto SketchPlane3d.yz direction\n    --> Just Direction2d.negativeX\n\n    Direction3d.projectInto SketchPlane3d.xy Direction3d.z\n    --> Nothing\n\n",
                "type": "SketchPlane3d -> Direction3d -> Maybe Direction2d"
            },
            {
                "name": "projectOnto",
                "comment": " Find the [orthographic projection](https://en.wikipedia.org/wiki/Orthographic_projection)\nof a direction onto a plane (renormalized to have unit length). If the given\ndirection is exactly perpendicular to the given plane, returns `Nothing`.\n\n    direction =\n        Direction3d.with\n            { azimuth = degrees -60\n            , elevation = 0\n            }\n\n    Direction3d.projectOnto Plane3d.xy direction\n    --> Just direction\n\n    Direction3d.projectOnto Plane3d.xz direction\n    --> Just Direction3d.x\n\n    Direction3d.projectOnto Plane3d.yz direction\n    --> Just Direction3d.negativeY\n\n    Direction3d.projectOnto Plane3d.xy Direction3d.z\n    --> Nothing\n\n",
                "type": "Plane3d -> Direction3d -> Maybe Direction3d"
            },
            {
                "name": "relativeTo",
                "comment": " Take a direction defined in global coordinates, and return it expressed in\nlocal coordinates relative to a given reference frame.\n\n    Direction3d.relativeTo rotatedFrame Direction3d.x\n    --> Direction3d.with\n    -->     { azimuth = degrees -30\n    -->     , elevation = 0\n    -->     }\n\n    Direction3d.relativeTo rotatedFrame Direction3d.y\n    --> Direction3d.with\n    -->     { azimuth = degrees 60\n    -->     , elevation = 0\n    -->     }\n\n    Direction3d.relativeTo rotatedFrame Direction3d.z\n    --> Direction3d.z\n\n",
                "type": "Frame3d -> Direction3d -> Direction3d"
            },
            {
                "name": "rotateAround",
                "comment": " Rotate a direction around an axis by a given angle.\n\n    Direction3d.y\n        |> Direction3d.rotateAround Axis3d.x (degrees 90)\n    --> Direction3d.z\n\nNote that only the direction of the axis affects the result, not the position of\nits origin point, since directions are position-independent:\n\n    offsetAxis =\n        Axis3d\n            { originPoint =\n                Point3d.fromCoordinates ( 100, 200, 300 )\n            , direction = Direction3d.z\n            }\n\n    Direction3d.x\n        |> Direction3d.rotateAround offsetAxis (degrees 90)\n    --> Direction3d.y\n\n",
                "type": "Axis3d -> Float -> Direction3d -> Direction3d"
            },
            {
                "name": "toVector",
                "comment": " Convert a direction to a unit vector.\n\n    Direction3d.toVector Direction3d.y\n    --> Vector3d.fromComponents ( 0, 1, 0 )\n\n",
                "type": "Direction3d -> Vector3d"
            },
            {
                "name": "unsafe",
                "comment": " Construct a direction directly from its X, Y and Z components. Note that\n**you must ensure that the sum of the squares of the given components is exactly\none**:\n\n    Direction3d.unsafe ( 1, 0, 0 )\n    Direction3d.unsafe ( 0, -1, 0 )\n    Direction3d.unsafe ( 0.6, 0, 0.8 )\n\nare all valid but\n\n    Direction3d.unsafe ( 2, 0, 0 )\n    Direction3d.unsafe ( 1, 1, 1 )\n\nare not. Instead of using `Direction3d.unsafe`, it may be easier to use\nconstructors like `Direction3d.on` or `Direction3d.with` (which will always\nresult in a valid direction), or start with existing directions and transform\nthem as necessary.\n\n",
                "type": "( Float, Float, Float ) -> Direction3d"
            },
            {
                "name": "with",
                "comment": " Construct a direction using azimuthal and elevation angles relative to the\nglobal XYZ frame. The azimuth defines the direction's polar angle on the global\nXY plane (from X towards Y) and the elevation defines its angle out of the XY\nplane towards positive Z.\n\n    Direction3d.components\n        (Direction3d.with\n            { azimuth = degrees 45\n            , elevation = degrees 45\n            }\n        )\n    --> ( 0.5, 0.5, 0.7071 )\n\n",
                "type": "{ azimuth : Float, elevation : Float } -> Direction3d"
            },
            {
                "name": "x",
                "comment": " Synonym for `Direction3d.positiveX`.\n",
                "type": "Direction3d"
            },
            {
                "name": "xComponent",
                "comment": " Get the X component of a direction.\n\n    Direction3d.xComponent Direction3d.x\n    --> 1\n\n    Direction3d.xComponent Direction3d.y\n    --> 0\n\n",
                "type": "Direction3d -> Float"
            },
            {
                "name": "y",
                "comment": " Synonym for `Direction3d.positiveY`.\n",
                "type": "Direction3d"
            },
            {
                "name": "yComponent",
                "comment": " Get the Y component of a direction.\n\n    Direction3d.yComponent Direction3d.y\n    --> 1\n\n    Direction3d.yComponent Direction3d.z\n    --> 0\n\n",
                "type": "Direction3d -> Float"
            },
            {
                "name": "z",
                "comment": " Synonym for `Direction3d.positiveZ`.\n",
                "type": "Direction3d"
            },
            {
                "name": "zComponent",
                "comment": " Get the Z component of a direction.\n\n    Direction3d.zComponent Direction3d.z\n    --> 1\n\n    Direction3d.zComponent Direction3d.x\n    --> 0\n\n",
                "type": "Direction3d -> Float"
            }
        ],
        "binops": []
    },
    {
        "name": "OpenSolid.Point2d",
        "comment": " <img src=\"https://opensolid.github.io/images/geometry/icons/point2d.svg\" alt=\"Point2d\" width=\"160\">\n\nA `Point2d` represents a position in 2D space and is defined by its X and Y\ncoordinates. This module contains a variety of point-related functionality, such\nas\n\n  - Measuring distance between points\n  - Scaling, rotating, translating, mirroring and projecting points\n  - Converting points between different coordinate systems\n\nPoints are distinct from vectors but interact with them in well-defined ways;\nyou can translate a point by a vector to result in a new point, or you can\ncompute the vector from one point to another, but you cannot 'add' two points\nlike you can add two vectors.\n\n@docs Point2d\n\n\n# Constants\n\n@docs origin\n\n\n# Constructors\n\n@docs fromCoordinates, fromPolarCoordinates, midpoint, interpolateFrom, along, in_, circumcenter\n\n\n# Properties\n\n@docs coordinates, xCoordinate, yCoordinate, polarCoordinates\n\n\n# Comparison\n\n@docs equalWithin\n\n\n# Measurement\n\n@docs distanceFrom, squaredDistanceFrom, signedDistanceAlong, distanceAlong, signedDistanceFrom\n\n\n# Transformations\n\n@docs scaleAbout, rotateAround, translateBy, mirrorAcross, projectOnto\n\n\n# Coordinate conversions\n\nFunctions for transforming points between local and global coordinates in\ndifferent coordinate frames.\n\n@docs relativeTo, placeIn\n\n\n# Bounding box construction\n\n@docs hull, hullOf\n\n",
        "unions": [],
        "aliases": [
            {
                "name": "Point2d",
                "comment": " ",
                "args": [],
                "type": "Point2d"
            }
        ],
        "values": [
            {
                "name": "along",
                "comment": " Construct a point along an axis at a particular distance from the axis'\norigin point.\n\n    Point2d.along Axis2d.y 3\n    --> Point2d.fromCoordinates ( 0, 3 )\n\nPositive and negative distances will be interpreted relative to the direction of\nthe axis:\n\n    horizontalAxis =\n        Axis2d.with\n            { originPoint =\n                Point2d.fromCoordinates ( 1, 1 )\n            , direction = Direction2d.negativeX\n            }\n\n    Point2d.along horizontalAxis 3\n    --> Point2d.fromCoordinates ( -2, 1 )\n\n    Point2d.along horizontalAxis -3\n    --> Point2d.fromCoordinates ( 4, 1 )\n\n",
                "type": "Axis2d -> Float -> Point2d"
            },
            {
                "name": "circumcenter",
                "comment": " Attempt to find the circumcenter of three points; this is the center of the\ncircle that passes through all three points. If the three given points are\ncollinear, returns `Nothing`.\n\n    Point2d.circumcenter\n        ( Point2d.origin\n        , Point2d.fromCoordinates ( 1, 0 )\n        , Point2d.fromCoordinates ( 0, 1 )\n        )\n    --> Just (Point2d.fromCoordinates ( 0.5, 0.5 ))\n\n    Point2d.circumcenter\n        ( Point2d.origin\n        , Point2d.fromCoordinates ( 2, 1 )\n        , Point2d.fromCoordinates ( 4, 0 )\n        )\n    --> Just (Point2d.fromCoordinates ( 2, -1.5 ))\n\n    Point2d.circumCenter\n        ( Point2d.origin\n        , Point2d.fromCoordinates ( 2, 0 )\n        , Point2d.fromCoordinates ( 4, 0 )\n        )\n    --> Nothing\n\n    Point2d.circumCenter\n        ( Point2d.origin\n        , Point2d.origin\n        , Point2d.fromCoordinates ( 1, 0 )\n        )\n    --> Nothing\n\n",
                "type": "( Point2d, Point2d, Point2d ) -> Maybe Point2d"
            },
            {
                "name": "coordinates",
                "comment": " Get the coordinates of a point as a tuple.\n\n    ( x, y ) =\n        Point2d.coordinates point\n\n",
                "type": "Point2d -> ( Float, Float )"
            },
            {
                "name": "distanceAlong",
                "comment": " DEPRECATED: Alias for `signedDistanceAlong`, kept for compatibility. Use\n`signedDistanceAlong` instead.\n",
                "type": "Axis2d -> Point2d -> Float"
            },
            {
                "name": "distanceFrom",
                "comment": " Find the distance from the first point to the second.\n\n    p1 =\n        Point2d.fromCoordinates ( 2, 3 )\n\n    p2 =\n        Point2d.fromCoordinates ( 5, 7 )\n\n    Point2d.distanceFrom p1 p2\n    --> 5\n\nPartial application can be useful:\n\n    points =\n        [ Point2d.fromCoordinates ( 3, 4 )\n        , Point2d.fromCoordinates ( 10, 0 )\n        , Point2d.fromCoordinates ( -1, 2 )\n        ]\n\n    points\n        |> List.sortBy\n            (Point2d.distanceFrom Point2d.origin)\n    --> [ Point2d.fromCoordinates ( -1, 2 )\n    --> , Point2d.fromCoordinates ( 3, 4 )\n    --> , Point2d.fromCoordinates ( 10, 0 )\n    --> ]\n\n",
                "type": "Point2d -> Point2d -> Float"
            },
            {
                "name": "equalWithin",
                "comment": " Compare two points within a tolerance. Returns true if the distance\nbetween the two given points is less than the given tolerance.\n\n    firstPoint =\n        Point2d.fromCoordinates ( 1, 2 )\n\n    secondPoint =\n        Point2d.fromCoordinates ( 0.9999, 2.0002 )\n\n    Point2d.equalWithin 1e-3 firstPoint secondPoint\n    --> True\n\n    Point2d.equalWithin 1e-6 firstPoint secondPoint\n    --> False\n\n",
                "type": "Float -> Point2d -> Point2d -> Bool"
            },
            {
                "name": "fromCoordinates",
                "comment": " Construct a point from its X and Y coordinates.\n\n    point =\n        Point2d.fromCoordinates ( 2, 3 )\n\n",
                "type": "( Float, Float ) -> Point2d"
            },
            {
                "name": "fromPolarCoordinates",
                "comment": " Construct a point from a radius and angle. Radius is measured from the\norigin and angle is measured counterclockwise from the positive X direction.\n\n    Point2d.fromPolarCoordinates ( 2, degrees 135 )\n    --> Point2d.fromCoordinates ( -1.4142, 1.4142 )\n\n",
                "type": "( Float, Float ) -> Point2d"
            },
            {
                "name": "hull",
                "comment": " Construct a bounding box containing both of the given points.\n\n    point1 =\n        Point2d.fromCoordinates ( 2, 3 )\n\n    point2 =\n        Point2d.fromCoordinates ( -1, 5 )\n\n    Point2d.hull point1 point2\n    --> BoundingBox2d.with\n    -->     { minX = -1\n    -->     , maxX = 2\n    -->     , minY = 3\n    -->     , maxY = 5\n    -->     }\n\n",
                "type": "Point2d -> Point2d -> BoundingBox2d"
            },
            {
                "name": "hullOf",
                "comment": " Construct a bounding box containing all points in the given list. If the\nlist is empty, returns `Nothing`.\n\n    points =\n        [ Point2d.fromCoordinates ( 2, 3 )\n        , Point2d.fromCoordinates ( -1, 5 )\n        , Point2d.fromCoordinates ( 6, 4 )\n        ]\n\n    Point2d.hullOf points\n    --> Just\n    -->     (BoundingBox2d.with\n    -->         { minX = -1\n    -->         , maxX = 6\n    -->         , minY = 3\n    -->         , maxY = 5\n    -->         }\n    -->     )\n\n    Point2d.hullOf []\n    --> Nothing\n\n",
                "type": "List Point2d -> Maybe BoundingBox2d"
            },
            {
                "name": "in_",
                "comment": " Construct a point given its local coordinates within a particular frame.\n\n    rotatedFrame =\n        Frame2d.xy |> Frame2d.rotateBy (degrees 45)\n\n    Point2d.in_ rotatedFrame ( 2, 0 )\n    --> Point2d.fromCoordinates ( 1.4142, 1.4142 )\n\nThis is shorthand for using `Point2d.placeIn`;\n\n    Point2d.in_ frame coordinates\n\nis equivalent to\n\n    Point2d.placeIn frame\n        (Point2d.fromCoordinates coordinates)\n\n",
                "type": "Frame2d -> ( Float, Float ) -> Point2d"
            },
            {
                "name": "interpolateFrom",
                "comment": " Construct a point by interpolating from the first given point to the second,\nbased on a parameter that ranges from zero to one.\n\n    startPoint =\n        Point2d.origin\n\n    endPoint =\n        Point2d.fromCoordinates ( 8, 12 )\n\n    Point2d.interpolateFrom startPoint endPoint 0.25\n    --> Point2d.fromCoordinates ( 2, 3 )\n\nPartial application may be useful:\n\n    interpolatedPoint : Float -> Point2d\n    interpolatedPoint =\n        Point2d.interpolateFrom startPoint endPoint\n\n    List.map interpolatedPoint [ 0, 0.5, 1 ]\n    --> [ Point2d.fromCoordinates ( 0, 0 )\n    --> , Point2d.fromCoordinates ( 4, 6 )\n    --> , Point2d.fromCoordinates ( 8, 12 )\n    --> ]\n\nYou can pass values less than zero or greater than one to extrapolate:\n\n    interpolatedPoint -0.5\n    --> Point2d.fromCoordinates ( -4, -6 )\n\n    interpolatedPoint 1.25\n    --> Point2d.fromCoordinates ( 10, 15 )\n\n",
                "type": "Point2d -> Point2d -> Float -> Point2d"
            },
            {
                "name": "midpoint",
                "comment": " Construct a point halfway between two other points.\n\n    p1 =\n        Point2d.fromCoordinates ( 1, 1 )\n\n    p2 =\n        Point2d.fromCoordinates ( 3, 7 )\n\n    Point2d.midpoint p1 p2\n    --> Point2d.fromCoordinates ( 2, 4 )\n\n",
                "type": "Point2d -> Point2d -> Point2d"
            },
            {
                "name": "mirrorAcross",
                "comment": " Mirror a point across an axis. The result will be the same distance from the\naxis but on the opposite side.\n\n    point =\n        Point2d.fromCoordinates ( 2, 3 )\n\n    Point2d.mirrorAcross Axis2d.x point\n    --> Point2d.fromCoordinates ( 2, -3 )\n\n    Point2d.mirrorAcross Axis2d.y point\n    --> Point2d.fromCoordinates ( -2, 3 )\n\n",
                "type": "Axis2d -> Point2d -> Point2d"
            },
            {
                "name": "origin",
                "comment": " The point (0, 0).\n\n    Point2d.origin\n    --> Point2d.fromCoordinates ( 0, 0 )\n\n",
                "type": "Point2d"
            },
            {
                "name": "placeIn",
                "comment": " Take a point defined in local coordinates relative to a given reference\nframe, and return that point expressed in global coordinates.\n\n    localFrame =\n        Frame2d.atPoint (Point2d.fromCoordinates ( 1, 2 ))\n\n    Point2d.placeIn localFrame\n        (Point2d.fromCoordinates ( 3, 3 ))\n    --> Point2d.fromCoordinates ( 4, 5 )\n\n    Point2d.placeIn localFrame\n        (Point2d.fromCoordinates ( 0, 1 ))\n    --> Point2d.fromCoordinates ( 1, 1 )\n\n",
                "type": "Frame2d -> Point2d -> Point2d"
            },
            {
                "name": "polarCoordinates",
                "comment": " Get the polar coordinates (radius and polar angle) of a point.\n\n    Point2d.polarCoordinates\n        (Point2d.fromCoordinates ( 1, 1 ))\n    --> ( 1.4142, degrees 45 )\n\n",
                "type": "Point2d -> ( Float, Float )"
            },
            {
                "name": "projectOnto",
                "comment": " Project a point perpendicularly onto an axis.\n\n    point =\n        Point2d.fromCoordinates ( 2, 3 )\n\n    Point2d.projectOnto Axis2d.x point\n    --> Point2d.fromCoordinates ( 2, 0 )\n\n    Point2d.projectOnto Axis2d.y point\n    --> Point2d.fromCoordinates ( 0, 3 )\n\nThe axis does not have to pass through the origin:\n\n    offsetYAxis =\n        Axis2d.with\n            { originPoint =\n                Point2d.fromCoordinates ( 1, 0 )\n            , direction = Direction2d.y\n            }\n\n    Point2d.projectOnto offsetYAxis point\n    --> Point2d.fromCoordinates ( 1, 3 )\n\n",
                "type": "Axis2d -> Point2d -> Point2d"
            },
            {
                "name": "relativeTo",
                "comment": " Take a point defined in global coordinates, and return it expressed in local\ncoordinates relative to a given reference frame.\n\n    localFrame =\n        Frame2d.atPoint (Point2d.fromCoordinates ( 1, 2 ))\n\n    Point2d.relativeTo localFrame\n        (Point2d.fromCoordinates ( 4, 5 ))\n    --> Point2d.fromCoordinates ( 3, 3 )\n\n    Point2d.relativeTo localFrame\n        (Point2d.fromCoordinates ( 1, 1 ))\n    --> Point2d.fromCoordinates ( 0, -1 )\n\n",
                "type": "Frame2d -> Point2d -> Point2d"
            },
            {
                "name": "rotateAround",
                "comment": " Rotate around a given center point counterclockwise by a given angle (in\nradians). The point to rotate around is given first and the point to rotate is\ngiven last.\n\n    centerPoint =\n        Point2d.fromCoordinates ( 2, 0 )\n\n    angle =\n        degrees 45\n\n    point =\n        Point2d.fromCoordinates ( 3, 0 )\n\n    Point2d.rotateAround centerPoint angle point\n    --> Point2d.fromCoordinates ( 2.7071, 0.7071 )\n\n",
                "type": "Point2d -> Float -> Point2d -> Point2d"
            },
            {
                "name": "scaleAbout",
                "comment": " Perform a uniform scaling about the given center point. The center point is\ngiven first and the point to transform is given last. Points will contract or\nexpand about the center point by the given scale. Scaling by a factor of 1 is a\nno-op, and scaling by a factor of 0 collapses all points to the center point.\n\n    centerPoint =\n        Point2d.fromCoordinates ( 1, 1 )\n\n    point =\n        Point2d.fromCoordinates ( 2, 3 )\n\n    Point2d.scaleAbout centerPoint 3 point\n    --> Point2d.fromCoordinates ( 4, 7 )\n\n    Point2d.scaleAbout centerPoint 0.5 point\n    --> Point2d.fromCoordinates ( 1.5, 2 )\n\nAvoid scaling by a negative scaling factor - while this may sometimes do what\nyou want it is confusing and error prone. Try a combination of mirror and/or\nrotation operations instead.\n\n",
                "type": "Point2d -> Float -> Point2d -> Point2d"
            },
            {
                "name": "signedDistanceAlong",
                "comment": " Determine how far along an axis a particular point lies. Conceptually, the\npoint is projected perpendicularly onto the axis, and then the distance of this\nprojected point from the axis' origin point is measured. The result will be\npositive if the projected point is ahead the axis' origin point and negative if\nit is behind, with 'ahead' and 'behind' defined by the direction of the axis.\n\n    axis =\n        Axis2d.with\n            { originPoint =\n                Point2d.fromCoordinates ( 1, 2 )\n            , direction = Direction2d.x\n            }\n\n    point =\n        Point2d.fromCoordinates ( 3, 3 )\n\n    Point2d.signedDistanceAlong axis point\n    --> 2\n\n    Point2d.signedDistanceAlong axis Point2d.origin\n    --> -1\n\n",
                "type": "Axis2d -> Point2d -> Float"
            },
            {
                "name": "signedDistanceFrom",
                "comment": " Find the perpendicular distance of a point from an axis. The result\nwill be positive if the point is to the left of the axis and negative if it is\nto the right, with the forwards direction defined by the direction of the axis.\n\n    -- A horizontal axis through a point with a Y\n    -- coordinate of 2 is effectively the line Y=2\n    axis =\n        Axis2d.with\n            { originPoint =\n                Point2d.fromCoordinates ( 1, 2 )\n            , direction = Direction2d.x\n            }\n\n    point =\n        Point2d.fromCoordinates ( 3, 3 )\n\n    -- Since the axis is in the positive X direction,\n    -- points above the axis are to the left (positive)\n    Point2d.signedDistanceFrom axis point\n    -->  1\n\n    -- and points below are to the right (negative)\n    Point2d.signedDistanceFrom axis Point2d.origin\n    --> -2\n\nThis means that flipping an axis will also flip the sign of the result of this\nfunction:\n\n    -- Flipping an axis reverses its direction\n    flippedAxis =\n        Axis2d.flip axis\n\n    Point2d.signedDistanceFrom flippedAxis point\n    --> -1\n\n    Point2d.signedDistanceFrom flippedAxis Point2d.origin\n    --> 2\n\n",
                "type": "Axis2d -> Point2d -> Float"
            },
            {
                "name": "squaredDistanceFrom",
                "comment": " Find the square of the distance from one point to another.\n`squaredDistanceFrom` is slightly faster than `distanceFrom`, so for example\n\n    Point2d.squaredDistanceFrom p1 p2\n        > tolerance * tolerance\n\nis equivalent to but slightly more efficient than\n\n    Point2d.distanceFrom p1 p2 > tolerance\n\nsince the latter requires a square root under the hood. In many cases, however,\nthe speed difference will be negligible and using `distanceFrom` is much more\nreadable!\n\n",
                "type": "Point2d -> Point2d -> Float"
            },
            {
                "name": "translateBy",
                "comment": " Translate a point by a given displacement.\n\n    point =\n        Point2d.fromCoordinates ( 3, 4 )\n\n    displacement =\n        Vector2d.fromComponents ( 1, 2 )\n\n    Point2d.translateBy displacement point\n    --> Point2d.fromCoordinates ( 4, 6 )\n\n",
                "type": "Vector2d -> Point2d -> Point2d"
            },
            {
                "name": "xCoordinate",
                "comment": " Get the X coordinate of a point.\n\n    Point2d.xCoordinate (Point2d.fromCoordinates ( 2, 3 ))\n    --> 2\n\n",
                "type": "Point2d -> Float"
            },
            {
                "name": "yCoordinate",
                "comment": " Get the Y coordinate of a point.\n\n    Point2d.yCoordinate (Point2d.fromCoordinates ( 2, 3 ))\n    --> 3\n\n",
                "type": "Point2d -> Float"
            }
        ],
        "binops": []
    },
    {
        "name": "OpenSolid.Vector3d",
        "comment": " <img src=\"https://opensolid.github.io/images/geometry/icons/vector3d.svg\" alt=\"Vector3d\" width=\"160\">\n\nA `Vector3d` represents a quantity such as a displacement or velocity in 3D, and\nis defined by its X, Y and Z components. This module contains a variety of\nvector-related functionality, such as\n\n  - Adding or subtracting vectors\n  - Finding the lengths of vectors\n  - Rotating vectors\n  - Converting vectors between different coordinate systems\n\nNote that unlike in many other geometry packages where vectors are used as a\ngeneral-purpose data type, OpenSolid has separate data types for vectors,\ndirections and points. In most code it is actually more common to use `Point3d`\nand `Direction3d` than `Vector3d`, and much code can avoid working directly with\n`Vector3d` values at all!\n\n@docs Vector3d\n\n\n# Predefined vectors\n\n@docs zero\n\nAlthough there are no predefined constants for the vectors with components\n(1,&nbsp;0,&nbsp;0), (0,&nbsp;1,&nbsp;0) and (0,&nbsp;0,&nbsp;1), in most cases\nyou will actually want their `Direction3d` versions [`Direction3d.x`](OpenSolid-Direction3d#x),\n[`Direction3d.y`](OpenSolid-Direction3d#y) and [`Direction3d.z`](OpenSolid-Direction3d#z).\n\n\n# Constructors\n\n@docs fromComponents, from, with, on, perpendicularTo, interpolateFrom\n\n\n# Components\n\n@docs components, xComponent, yComponent, zComponent, length, squaredLength, direction, lengthAndDirection\n\n\n# Comparison\n\n@docs equalWithin\n\n\n# Measurement\n\n@docs componentIn\n\n\n# Arithmetic\n\n@docs sum, difference, dotProduct, crossProduct\n\n\n# Transformations\n\nNote that for all transformations, only the orientation of the given axis or\nplane is relevant, since vectors are position-independent. Think of transforming\na vector as placing its tail on the relevant axis or plane and then transforming\nits tip.\n\n@docs flip, normalize, scaleBy, rotateAround, mirrorAcross, projectionIn, projectOnto\n\n\n# Coordinate conversions\n\nFunctions for transforming vectors between local and global coordinates in\ndifferent coordinate frames. Like other transformations, coordinate\ntransformations of vectors depend only on the orientations of the relevant\nframes/sketch planes, not their positions.\n\nFor the examples, assume the following definition of a local coordinate frame,\none that is rotated 30 degrees counterclockwise around the Z axis from the\nglobal XYZ frame:\n\n    rotatedFrame =\n        Frame3d.rotateAround Axis3d.z (degrees 30) Frame3d.xyz\n\n@docs relativeTo, placeIn, projectInto\n\n",
        "unions": [],
        "aliases": [
            {
                "name": "Vector3d",
                "comment": " ",
                "args": [],
                "type": "Vector3d"
            }
        ],
        "values": [
            {
                "name": "componentIn",
                "comment": " Find the component of a vector in an arbitrary direction, for example\n\n    verticalSpeed =\n        Vector3d.componentIn upDirection velocity\n\nThis is more general and flexible than using `xComponent`, `yComponent` or\n`zComponent`, all of which can be expressed in terms of `componentIn`; for\nexample,\n\n    Vector3d.zComponent vector\n\nis equivalent to\n\n    Vector3d.componentIn Direction3d.z vector\n\n",
                "type": "Direction3d -> Vector3d -> Float"
            },
            {
                "name": "components",
                "comment": " Extract the components of a vector.\n\n    Vector3d.fromComponents ( 2, 3, 4 )\n        |> Vector3d.components\n    --> ( 2, 3, 4 )\n\nThis combined with Elm's built-in tuple destructuring provides a convenient way\nto extract the X, Y and Z components of a vector in one line of code:\n\n    ( x, y, z ) =\n        Vector3d.components vector\n\n",
                "type": "Vector3d -> ( Float, Float, Float )"
            },
            {
                "name": "crossProduct",
                "comment": " Find the cross product of two vectors.\n\n    firstVector =\n        Vector3d.fromComponents ( 2, 0, 0 )\n\n    secondVector =\n        Vector3d.fromComponents ( 0, 3, 0 )\n\n    Vector3d.crossProduct firstVector secondVector\n    --> Vector3d.fromComponents ( 0, 0, 6 )\n\n",
                "type": "Vector3d -> Vector3d -> Vector3d"
            },
            {
                "name": "difference",
                "comment": " Find the difference between two vectors (the first vector minus the second).\n\n    firstVector =\n        Vector3d.fromComponents ( 5, 6, 7 )\n\n    secondVector =\n        Vector3d.fromComponents ( 1, 1, 1 )\n\n    Vector3d.difference firstVector secondVector\n    --> Vector3d.fromComponents ( 4, 5, 6 )\n\n",
                "type": "Vector3d -> Vector3d -> Vector3d"
            },
            {
                "name": "direction",
                "comment": " Attempt to find the direction of a vector. In the case of a zero vector,\nreturns `Nothing`.\n\n    Vector3d.fromComponents ( 3, 0, 3 )\n        |> Vector3d.direction\n    --> Just\n    -->     (Direction3d.with\n    -->         { azimuth = 0\n    -->         , elevation = degrees 45\n    -->         }\n    -->     )\n\n    Vector3d.direction Vector3d.zero\n    --> Nothing\n\n",
                "type": "Vector3d -> Maybe Direction3d"
            },
            {
                "name": "dotProduct",
                "comment": " Find the dot product of two vectors.\n\n    firstVector =\n        Vector3d.fromComponents ( 1, 0, 2 )\n\n    secondVector =\n        Vector3d.fromComponents ( 3, 4, 5 )\n\n    Vector3d.dotProduct firstVector secondVector\n    --> 13\n\n",
                "type": "Vector3d -> Vector3d -> Float"
            },
            {
                "name": "equalWithin",
                "comment": " Compare two vectors within a tolerance. Returns true if the difference\nbetween the two given vectors has magnitude less than the given tolerance.\n\n    firstVector =\n        Vector3d.fromComponents ( 2, 1, 3 )\n\n    secondVector =\n        Vector3d.fromComponents ( 2.0002, 0.9999, 3.0001 )\n\n    Vector3d.equalWithin 1e-3 firstVector secondVector\n    --> True\n\n    Vector3d.equalWithin 1e-6 firstVector secondVector\n    --> False\n\n",
                "type": "Float -> Vector3d -> Vector3d -> Bool"
            },
            {
                "name": "flip",
                "comment": " Reverse the direction of a vector, negating its components.\n\n    Vector3d.flip (Vector3d.fromComponents ( 1, -3, 2 ))\n    --> Vector3d.fromComponents ( -1, 3, -2 )\n\n",
                "type": "Vector3d -> Vector3d"
            },
            {
                "name": "from",
                "comment": " Construct a vector from the first given point to the second.\n\n    startPoint =\n        Point3d.fromCoordinates ( 1, 1, 1 )\n\n    endPoint =\n        Point3d.fromCoordinates ( 4, 5, 6 )\n\n    Vector3d.from startPoint endPoint\n    --> Vector3d.fromComponents ( 3, 4, 5 )\n\n",
                "type": "Point3d -> Point3d -> Vector3d"
            },
            {
                "name": "fromComponents",
                "comment": " Construct a vector from its X, Y and Z components.\n\n    vector =\n        Vector3d.fromComponents ( 2, 1, 3 )\n\n",
                "type": "( Float, Float, Float ) -> Vector3d"
            },
            {
                "name": "interpolateFrom",
                "comment": " Construct a vector by interpolating from the first given vector to the\nsecond, based on a parameter that ranges from zero to one.\n\n    startVector =\n        Vector3d.fromComponents ( 1, 2, 4 )\n\n    endVector =\n        Vector3d.fromComponents ( 1, 3, 8 )\n\n    Vector3d.interpolateFrom startVector endVector 0.25\n    --> Vector3d.fromComponents ( 1, 2.25, 5 )\n\nPartial application may be useful:\n\n    interpolatedVector : Float -> Vector3d\n    interpolatedVector =\n        Vector3d.interpolateFrom startVector endVector\n\n    List.map interpolatedVector [ 0, 0.5, 1 ]\n    --> [ Vector3d.fromComponents ( 1, 2, 4 )\n    --> , Vector3d.fromComponents ( 1, 2, 6 )\n    --> , Vector3d.fromComponents ( 1, 2, 8 )\n    --> ]\n\nYou can pass values less than zero or greater than one to extrapolate:\n\n    interpolatedVector -0.5\n    --> Vector3d.fromComponents ( 1, 2, 2 )\n\n    interpolatedVector 1.25\n    --> Vector3d.fromComponents ( 1, 2, 9 )\n\n",
                "type": "Vector3d -> Vector3d -> Float -> Vector3d"
            },
            {
                "name": "length",
                "comment": " Get the length (magnitude) of a vector.\n\n    Vector3d.length (Vector3d.fromComponents ( 2, 1, 2 ))\n    --> 3\n\n",
                "type": "Vector3d -> Float"
            },
            {
                "name": "lengthAndDirection",
                "comment": " Attempt to find the length and direction of a vector. In the case of a zero\nvector, returns `Nothing`.\n\n    vector =\n        Vector3d.fromComponents ( 3, 0, 3 )\n\n    Vector3d.lengthAndDirection vector\n    --> Just\n    -->     ( 5\n    -->     , Direction3d.with\n    -->         { azimuth = 0\n    -->         , elevation = degrees 45\n    -->         }\n    -->     )\n\n    Vector3d.lengthAndDirection Vector3d.zero\n    --> Nothing\n\n",
                "type": "Vector3d -> Maybe ( Float, Direction3d )"
            },
            {
                "name": "mirrorAcross",
                "comment": " Mirror a vector across a plane.\n\n    vector =\n        Vector3d.fromComponents ( 1, 2, 3 )\n\n    Vector3d.mirrorAcross Plane3d.xy vector\n    --> Vector3d.fromComponents ( 1, 2, -3 )\n\n    Vector3d.mirrorAcross Plane3d.yz vector\n    --> Vector3d.fromComponents ( -1, 2, 3 )\n\n",
                "type": "Plane3d -> Vector3d -> Vector3d"
            },
            {
                "name": "normalize",
                "comment": " Normalize a vector to have a length of one. Zero vectors are left as-is.\n\n    vector =\n        Vector3d.fromComponents ( 3, 0, 4 )\n\n    Vector3d.normalize vector\n    --> Vector3d.fromComponents ( 0.6, 0, 0.8 )\n\n    Vector3d.normalize Vector3d.zero\n    --> Vector3d.zero\n\n**Warning**: `Vector3d.direction` is safer since it forces you to explicitly\nconsider the case where the given vector is zero. `Vector3d.normalize` is\nprimarily useful for cases like generating WebGL meshes, where defaulting to a\nzero vector for degenerate cases is acceptable, and the overhead of something\nlike\n\n    Vector3d.direction vector\n        |> Maybe.map Direction3d.toVector\n        |> Maybe.withDefault Vector3d.zero\n\n(which is functionally equivalent to `Vector3d.normalize vector`) is too high.\n\n",
                "type": "Vector3d -> Vector3d"
            },
            {
                "name": "on",
                "comment": " Construct a 3D vector lying _on_ a sketch plane by providing a 2D vector\nspecified in XY coordinates _within_ the sketch plane.\n\n    vector2d =\n        Vector2d.fromComponents ( 2, 3 )\n\n    Vector3d.on SketchPlane3d.xy vector2d\n    --> Vector3d.fromComponents ( 2, 3, 0 )\n\n    Vector3d.on SketchPlane3d.yz vector2d\n    --> Vector3d.fromComponents ( 0, 2, 3 )\n\n    Vector3d.on SketchPlane3d.zx vector2d\n    --> Vector3d.fromComponents ( 3, 0, 2 )\n\nA slightly more complex example:\n\n    tiltedSketchPlane =\n        SketchPlane3d.xy\n            |> SketchPlane3d.rotateAround Axis3d.x\n                (degrees 45)\n\n    Vector3d.on tiltedSketchPlane <|\n        Vector2d.fromComponents ( 1, 1 )\n    --> Vector3d.fromComponents ( 1, 0.7071, 0.7071 )\n\n",
                "type": "SketchPlane3d -> Vector2d -> Vector3d"
            },
            {
                "name": "perpendicularTo",
                "comment": " Construct an arbitrary vector perpendicular to the given vector. The exact\nlength and direction of the resulting vector are not specified, but it is\nguaranteed to be perpendicular to the given vector and non-zero (unless the\ngiven vector is itself zero).\n\n    Vector3d.perpendicularTo\n        (Vector3d.fromComponents ( 3, 0, 0 ))\n    --> Vector3d.fromComponents ( 0, 0, -3 )\n\n    Vector3d.perpendicularTo\n        (Vector3d.fromComponents ( 1, 2, 3 ))\n    --> Vector3d.fromComponents ( 0, -3, 2 )\n\n    Vector3d.perpendicularTo Vector3d.zero\n    --> Vector3d.zero\n\n",
                "type": "Vector3d -> Vector3d"
            },
            {
                "name": "placeIn",
                "comment": " Take a vector defined in local coordinates relative to a given reference\nframe, and return that vector expressed in global coordinates.\n\n    vector =\n        Vector3d.fromComponents ( 2, 0, 3 )\n\n    Vector3d.placeIn rotatedFrame vector\n    --> Vector3d.fromComponents ( 1.732, 1, 3 )\n\n",
                "type": "Frame3d -> Vector3d -> Vector3d"
            },
            {
                "name": "projectInto",
                "comment": " Project a vector into a given sketch plane. Conceptually, this finds the\n[orthographic projection](https://en.wikipedia.org/wiki/Orthographic_projection)\nof the vector onto the plane and then expresses the projected vector in 2D\nsketch coordinates.\n\n    vector =\n        Vector3d.fromComponents ( 2, 1, 3 )\n\n    Vector3d.projectInto SketchPlane3d.xy vector\n    --> Vector2d.fromComponents ( 2, 1 )\n\n    Vector3d.projectInto SketchPlane3d.yz vector\n    --> Vector2d.fromComponents ( 1, 3 )\n\n    Vector3d.projectInto SketchPlane3d.zx vector\n    --> Vector2d.fromComponents ( 3, 2 )\n\n",
                "type": "SketchPlane3d -> Vector3d -> Vector2d"
            },
            {
                "name": "projectOnto",
                "comment": " Project a vector [orthographically](https://en.wikipedia.org/wiki/Orthographic_projection)\nonto a plane. Conceptually, this means splitting the original vector into a\nportion parallel to the plane (perpendicular to the plane's normal direction)\nand a portion perpendicular to it (parallel to its normal direction), then\nreturning the parallel (in-plane) portion.\n\n    vector =\n        Vector3d.fromComponents ( 2, 1, 3 )\n\n    Vector3d.projectOnto Plane3d.xy vector\n    --> Vector3d.fromComponents ( 2, 1, 0 )\n\n    Vector3d.projectOnto Plane3d.xz vector\n    --> Vector3d.fromComponents ( 2, 0, 3 )\n\n",
                "type": "Plane3d -> Vector3d -> Vector3d"
            },
            {
                "name": "projectionIn",
                "comment": " Find the projection of a vector in a particular direction. Conceptually,\nthis means splitting the original vector into a portion parallel to the given\ndirection and a portion perpendicular to it, then returning the parallel\nportion.\n\n    vector =\n        Vector3d.fromComponents ( 1, 2, 3 )\n\n    Vector3d.projectionIn Direction3d.x vector\n    --> Vector3d.fromComponents ( 1, 0, 0 )\n\n    Vector3d.projectionIn Direction3d.z vector\n    --> Vector3d.fromComponents ( 0, 0, 3 )\n\n",
                "type": "Direction3d -> Vector3d -> Vector3d"
            },
            {
                "name": "relativeTo",
                "comment": " Take a vector defined in global coordinates, and return it expressed in\nlocal coordinates relative to a given reference frame.\n\n    vector =\n        Vector3d.fromComponents ( 2, 0, 3 )\n\n    Vector3d.relativeTo rotatedFrame vector\n    --> Vector3d.fromComponents ( 1.732, -1, 3 )\n\n",
                "type": "Frame3d -> Vector3d -> Vector3d"
            },
            {
                "name": "rotateAround",
                "comment": " Rotate a vector around a given axis by a given angle (in radians).\n\n    vector =\n        Vector3d.fromComponents ( 2, 0, 1 )\n\n    Vector3d.rotateAround Axis3d.x (degrees 90) vector\n    --> Vector3d.fromComponents ( 2, -1, 0 )\n\n    Vector3d.rotateAround Axis3d.z (degrees 45) vector\n    --> Vector3d.fromComponents ( 1.4142, 1.4142, 1 )\n\n",
                "type": "Axis3d -> Float -> Vector3d -> Vector3d"
            },
            {
                "name": "scaleBy",
                "comment": " Scale the length of a vector by a given scale.\n\n    Vector3d.fromComponents ( 1, 2, 3 )\n        |> Vector3d.scaleBy 3\n    --> Vector3d.fromComponents ( 3, 6, 9 )\n\n",
                "type": "Float -> Vector3d -> Vector3d"
            },
            {
                "name": "squaredLength",
                "comment": " Get the squared length of a vector. `squaredLength` is slightly faster than\n`length`, so for example\n\n    Vector3d.squaredLength vector > tolerance * tolerance\n\nis equivalent to but slightly more efficient than\n\n    Vector3d.length vector > tolerance\n\nsince the latter requires a square root under the hood. In many cases, however,\nthe speed difference will be negligible and using `length` is much more\nreadable!\n\n",
                "type": "Vector3d -> Float"
            },
            {
                "name": "sum",
                "comment": " Find the sum of two vectors.\n\n    firstVector =\n        Vector3d.fromComponents ( 1, 2, 3 )\n\n    secondVector =\n        Vector3d.fromComponents ( 4, 5, 6 )\n\n    Vector3d.sum firstVector secondVector\n    --> Vector3d.fromComponents ( 5, 7, 9 )\n\n",
                "type": "Vector3d -> Vector3d -> Vector3d"
            },
            {
                "name": "with",
                "comment": " Construct a vector with the given length in the given direction.\n\n    Vector3d.with { length = 5, direction = Direction3d.y }\n    --> Vector3d.fromComponents ( 0, 5, 0 )\n\n",
                "type": "{ length : Float, direction : Direction3d } -> Vector3d"
            },
            {
                "name": "xComponent",
                "comment": " Get the X component of a vector.\n\n    Vector3d.fromComponents ( 1, 2, 3 )\n        |> Vector3d.xComponent\n    --> 1\n\n",
                "type": "Vector3d -> Float"
            },
            {
                "name": "yComponent",
                "comment": " Get the Y component of a vector.\n\n    Vector3d.fromComponents ( 1, 2, 3 )\n        |> Vector3d.yComponent\n    --> 2\n\n",
                "type": "Vector3d -> Float"
            },
            {
                "name": "zComponent",
                "comment": " Get the Z component of a vector.\n\n    Vector3d.fromComponents ( 1, 2, 3 )\n        |> Vector3d.zComponent\n    --> 3\n\n",
                "type": "Vector3d -> Float"
            },
            {
                "name": "zero",
                "comment": " The zero vector.\n\n    Vector3d.zero\n    --> Vector3d.fromComponents ( 0, 0, 0 )\n\n",
                "type": "Vector3d"
            }
        ],
        "binops": []
    },
    {
        "name": "OpenSolid.Direction2d",
        "comment": " <img src=\"https://opensolid.github.io/images/geometry/icons/direction2d.svg\" alt=\"Direction2d\" width=\"160\">\n\nA `Direction2d` represents a direction like 'up' or 'north' or 'forwards'. They\nare represented using X and Y components, and can be converted to vectors if\nnecessary, but should be thought of as conceptually different. Directions have\nseveral uses, such as:\n\n  - Constructing a vector from a length and direction\n  - Determining the component of a vector in a particular direction (for\n    example, finding the component of velocity in the up direction to get\n    vertical speed)\n  - Determining the (signed) angle between two directions\n  - Defining the orientation of an axis or reference frame\n\n@docs Direction2d\n\n\n# Constants\n\n@docs x, y, positiveX, negativeX, positiveY, negativeY\n\n\n# Constructors\n\n@docs fromAngle, from, perpendicularTo, orthonormalize, orthogonalize, unsafe\n\n\n# Properties\n\n@docs components, xComponent, yComponent, angle\n\n\n# Comparison\n\n@docs equalWithin\n\n\n# Measurement\n\n@docs componentIn, angleFrom\n\n\n# Conversion\n\n@docs toVector\n\n\n# Transformations\n\n@docs flip, rotateClockwise, rotateCounterclockwise, rotateBy, mirrorAcross\n\n\n# Coordinate conversions\n\nFunctions for transforming directions between local and global coordinates in\ndifferent coordinate frames. Like other transformations, coordinate\ntransformations of directions depend only on the orientations of the relevant\nframes, not the positions of their origin points.\n\nFor the examples, assume the following frames have been defined:\n\n    upsideDownFrame =\n        Frame2d\n            { originPoint = Point2d.origin\n            , xDirection = Direction2d.positiveX\n            , yDirection = Direction2d.negativeY\n            }\n\n    rotatedFrame =\n        Frame2d.rotateBy (degrees 30) Frame2d.xy\n\n@docs relativeTo, placeIn\n\n",
        "unions": [],
        "aliases": [
            {
                "name": "Direction2d",
                "comment": " ",
                "args": [],
                "type": "Direction2d"
            }
        ],
        "values": [
            {
                "name": "angle",
                "comment": " Get the polar angle of a vector (its counterclockwise angle in radians from\nthe positive X direction). The result will be in the range -π to π.\n\n    Direction2d.angle Direction2d.x\n    --> 0\n\n    Direction2d.angle Direction2d.y\n    --> degrees 90\n\n    Direction2d.angle Direction2d.negativeY\n    --> degrees -90\n\n",
                "type": "Direction2d -> Float"
            },
            {
                "name": "angleFrom",
                "comment": " Find the counterclockwise angle in radians from the first direction to the\nsecond. The result will be in the range -π to π.\n\n    referenceDirection =\n        Direction2d.fromAngle (degrees 30)\n\n    Direction2d.angleFrom referenceDirection Direction2d.y\n    --> degrees 60\n\n    Direction2d.angleFrom referenceDirection Direction2d.x\n    --> degrees -30\n\n",
                "type": "Direction2d -> Direction2d -> Float"
            },
            {
                "name": "componentIn",
                "comment": " Find the component of one direction in another direction. This is equal to\nthe cosine of the angle between the directions, or equivalently the dot product\nof the two directions converted to unit vectors.\n\n    direction =\n        Direction2d.fromAngle (degrees 60)\n\n    Direction2d.componentIn Direction2d.x direction\n    --> 0.5\n\n    Direction2d.componentIn direction direction\n    --> 1\n\n    Direction2d.componentIn Direction2d.x Direction2d.y\n    --> 0\n\nThis is more general and flexible than using `xComponent` or `yComponent`, both\nof which can be expressed in terms of `componentIn`; for example,\n\n    Direction2d.xComponent direction\n\nis equivalent to\n\n    Direction2d.componentIn Direction2d.x direction\n\n",
                "type": "Direction2d -> Direction2d -> Float"
            },
            {
                "name": "components",
                "comment": " Get the components of a direction as a tuple (the components it would have\nas a unit vector, also know as its direction cosines).\n\n    ( x, y ) =\n        Direction2d.components direction\n\n",
                "type": "Direction2d -> ( Float, Float )"
            },
            {
                "name": "equalWithin",
                "comment": " Compare two directions within an angular tolerance. Returns true if the\nabsolute value of the angle between the two given directions is less than the\ngiven tolerance.\n\n    firstDirection =\n        Direction2d.fromAngle (degrees 45)\n\n    secondDirection =\n        Direction2d.fromAngle (degrees 47)\n\n    Direction2d.equalWithin (degrees 5)\n        firstDirection\n        secondDirection\n    --> True\n\n    Direction2d.equalWithin (degrees 1)\n        firstDirection\n        secondDirection\n    --> False\n\n",
                "type": "Float -> Direction2d -> Direction2d -> Bool"
            },
            {
                "name": "flip",
                "comment": " Reverse a direction.\n\n    Direction2d.flip Direction2d.y\n    --> Direction2d.negativeY\n\n",
                "type": "Direction2d -> Direction2d"
            },
            {
                "name": "from",
                "comment": " Attempt to construct the direction from the first given point to the second.\nIf the two points are coincident, returns `Nothing`.\n\n    point =\n        Point2d.fromCoordinates ( 1, 1 )\n\n    Direction2d.from Point2d.origin point\n    --> Just (Direction2d.fromAngle (degrees 45))\n\n    Direction2d.from point Point2d.origin\n    --> Just (Direction2d.fromAngle (degrees -135))\n\n    Direction2d.from point point\n    --> Nothing\n\n",
                "type": "Point2d -> Point2d -> Maybe Direction2d"
            },
            {
                "name": "fromAngle",
                "comment": " Construct a direction from an angle in radians, given counterclockwise from\nthe positive X direction.\n\n    Direction2d.fromAngle 0\n    --> Direction2d.x\n\n    Direction2d.fromAngle (degrees 90)\n    --> Direction2d.y\n\n    Direction2d.fromAngle (degrees -90)\n    --> Direction2d.negativeY\n\n",
                "type": "Float -> Direction2d"
            },
            {
                "name": "mirrorAcross",
                "comment": " Mirror a direction across a particular axis. Note that only the direction of\nthe axis affects the result, since directions are position-independent.\n\n    slopedAxis =\n        Axis2d.with\n            { originPoint =\n                Point2d.fromCoordinates ( 100, 200 )\n            , direction =\n                Direction2d.fromAngle (degrees 45)\n            }\n\n    Direction2d.mirrorAcross slopedAxis Direction2d.x\n    --> Direction2d.y\n\n    Direction2d.mirrorAcross slopedAxis Direction2d.y\n    --> Direction2d.x\n\n",
                "type": "Axis2d -> Direction2d -> Direction2d"
            },
            {
                "name": "negativeX",
                "comment": " The negative X direction.\n\n    Direction2d.components Direction2d.negativeX\n    --> ( -1, 0 )\n\n",
                "type": "Direction2d"
            },
            {
                "name": "negativeY",
                "comment": " The negative Y direction.\n\n    Direction2d.components Direction2d.negativeY\n    --> ( 0, -1 )\n\n",
                "type": "Direction2d"
            },
            {
                "name": "orthogonalize",
                "comment": " Attempt to form a pair of perpendicular directions from the two given\ndirections;\n\n    Direction2d.orthogonalize ( xDirection, yDirection )\n\nis equivalent to\n\n    Direction2d.orthonormalize\n        ( Direction2d.toVector xDirection\n        , Direction2d.toVector yDirection\n        )\n\n",
                "type": "( Direction2d, Direction2d ) -> Maybe ( Direction2d, Direction2d )"
            },
            {
                "name": "orthonormalize",
                "comment": " Attempt to form a pair of perpendicular directions from the two given\nvectors by performing [Gram-Schmidt normalization](https://en.wikipedia.org/wiki/Gram%E2%80%93Schmidt_process):\n\n  - The first returned direction will be equal to the direction of the first\n    given vector\n  - The second returned direction will be as close as possible to the second\n    given vector while being perpendicular to the first returned direction\n\nIf either of the given vectors are zero, or if the two vectors are parallel,\n`Nothing` will be returned.\n\n    Direction2d.orthonormalize\n        ( Vector2d.fromComponents ( 3, 3 )\n        , Vector2d.fromComponents ( 0, -2 )\n        )\n    --> Just\n    -->     ( Direction2d.fromAngle (degrees 45)\n    -->     , Direction2d.fromAngle (degrees -45)\n    -->     )\n\n    Direction2d.orthonormalize\n        ( Vector2d.fromComponents ( 3, 3 )\n        , Vector2d.fromComponents ( -2, -2 )\n        )\n    --> Nothing\n\n",
                "type": "( Vector2d, Vector2d ) -> Maybe ( Direction2d, Direction2d )"
            },
            {
                "name": "perpendicularTo",
                "comment": " Construct a direction perpendicular to the given direction, by rotating the\ngiven direction 90 degrees counterclockwise. Synonym for\n`rotateCounterclockwise`.\n\n    Direction2d.perpendicularTo Direction2d.x\n    --> Direction2d.y\n\n    Direction2d.perpendicularTo Direction2d.y\n    --> Direction2d.negativeX\n\n",
                "type": "Direction2d -> Direction2d"
            },
            {
                "name": "placeIn",
                "comment": " Take a direction defined in local coordinates relative to a given reference\nframe, and return that direction expressed in global coordinates.\n\n    Direction2d.placeIn upsideDownFrame Direction2d.y\n    --> Direction2d.negativeY\n\n    Direction2d.placeIn rotatedFrame Direction2d.x\n    --> Direction2d.fromAngle (degrees 30)\n\n    Direction2d.placeIn rotatedFrame Direction2d.y\n    --> Direction2d.fromAngle (degrees 120)\n\n",
                "type": "Frame2d -> Direction2d -> Direction2d"
            },
            {
                "name": "positiveX",
                "comment": " The positive X direction.\n\n    Direction2d.components Direction2d.positiveX\n    --> ( 1, 0 )\n\n",
                "type": "Direction2d"
            },
            {
                "name": "positiveY",
                "comment": " The positive Y direction.\n\n    Direction2d.components Direction2d.positiveY\n    --> ( 0, 1 )\n\n",
                "type": "Direction2d"
            },
            {
                "name": "relativeTo",
                "comment": " Take a direction defined in global coordinates, and return it expressed in\nlocal coordinates relative to a given reference frame.\n\n    Direction2d.relativeTo upsideDownFrame Direction2d.y\n    --> Direction2d.negativeY\n\n    Direction2d.relativeTo rotatedFrame Direction2d.x\n    --> Direction2d.fromAngle (degrees -30)\n\n    Direction2d.relativeTo rotatedFrame Direction2d.y\n    --> Direction2d.fromAngle (degrees 60)\n\n",
                "type": "Frame2d -> Direction2d -> Direction2d"
            },
            {
                "name": "rotateBy",
                "comment": " Rotate a direction counterclockwise by a given angle (in radians).\n\n    Direction2d.rotateBy pi Direction2d.x\n    --> Direction2d.negativeX\n\n    Direction2d.rotateBy (degrees 45) Direction2d.y\n    --> Direction2d.fromAngle (degrees 135)\n\n",
                "type": "Float -> Direction2d -> Direction2d"
            },
            {
                "name": "rotateClockwise",
                "comment": " Rotate a direction by 90 degrees clockwise.\n\n    Direction2d.rotateClockwise Direction2d.y\n    --> Direction2d.x\n\n    Direction2d.rotateClockwise Direction2d.x\n    --> Direction2d.negativeY\n\n",
                "type": "Direction2d -> Direction2d"
            },
            {
                "name": "rotateCounterclockwise",
                "comment": " Rotate a direction by 90 degrees counterclockwise.\n\n    Direction2d.rotateClockwise Direction2d.x\n    --> Direction2d.y\n\n    Direction2d.rotateClockwise Direction2d.y\n    --> Direction2d.negativeX\n\n",
                "type": "Direction2d -> Direction2d"
            },
            {
                "name": "toVector",
                "comment": " Convert a direction to a unit vector.\n\n    Direction2d.toVector Direction2d.x\n    --> Vector2d.fromComponents ( 1, 0 )\n\n",
                "type": "Direction2d -> Vector2d"
            },
            {
                "name": "unsafe",
                "comment": " Construct a direction directly from its X and Y components. Note that **you\nmust ensure that the sum of the squares of the given components is exactly\none**:\n\n    Direction2d.unsafe ( 1, 0 )\n    Direction2d.unsafe ( 0, -1 )\n    Direction2d.unsafe ( 0.6, 0.8 )\n\nare all valid but\n\n    Direction2d.unsafe ( 2, 0 )\n    Direction2d.unsafe ( 1, 1 )\n\nare not. Instead of using `Direction2d.unsafe`, it may be easier to use\nconstructors like `Direction2d.fromAngle` (which will always result in a valid\ndirection) or start with existing directions and transform them as necessary.\n\n",
                "type": "( Float, Float ) -> Direction2d"
            },
            {
                "name": "x",
                "comment": " Synonym for `Direction2d.positiveX`.\n",
                "type": "Direction2d"
            },
            {
                "name": "xComponent",
                "comment": " Get the X component of a direction.\n\n    Direction2d.xComponent Direction2d.x\n    --> 1\n\n    Direction2d.xComponent Direction2d.y\n    --> 0\n\n",
                "type": "Direction2d -> Float"
            },
            {
                "name": "y",
                "comment": " Synonym for `Direction2d.positiveY`.\n",
                "type": "Direction2d"
            },
            {
                "name": "yComponent",
                "comment": " Get the Y component of a direction.\n\n    Direction2d.yComponent Direction2d.x\n    --> 0\n\n    Direction2d.yComponent Direction2d.y\n    --> 1\n\n",
                "type": "Direction2d -> Float"
            }
        ],
        "binops": []
    },
    {
        "name": "OpenSolid.BoundingBox2d",
        "comment": " <img src=\"https://opensolid.github.io/images/geometry/icons/boundingBox2d.svg\" alt=\"BoundingBox2d\" width=\"160\">\n\nA `BoundingBox2d` is a rectangular box in 2D defined by its minimum and maximum\nX and Y values. It is possible to generate bounding boxes for most geometric\nobjects; for example, [`Triangle2d.boundingBox`](OpenSolid-Triangle2d#boundingBox)\ntakes a `Triangle2d` and returns a `BoundingBox2d` that contains that triangle.\nThere are several use cases where it is more efficient to deal with the bounding\nbox of an object than the object itself, such as:\n\n  - Intersection checking: If (for example) the bounding boxes of a line segment\n    and a triangle do not overlap, then the line segment and triangle cannot\n    possibly intersect each other. Expensive intersection checking therefore\n    only has to be performed for line segments and triangles whose bounding\n    boxes _do_ overlap.\n  - 2D rendering: When rendering a 2D scene, any object whose bounding box does\n    not overlap the viewing area must itself be completely outside the viewing\n    area, and therefore does not have to be drawn. This provides a simple form\n    of culling.\n\n@docs BoundingBox2d\n\n\n# Constructors\n\n@docs with, singleton, hull, intersection, hullOf\n\n\n# Properties\n\n@docs extrema, minX, maxX, minY, maxY, dimensions, midX, midY, centroid\n\n\n# Queries\n\n@docs contains, isContainedIn, intersects, overlaps, overlappingBy, separatedBy\n\n\n# Transformations\n\n@docs scaleAbout, translateBy\n\n",
        "unions": [],
        "aliases": [
            {
                "name": "BoundingBox2d",
                "comment": " ",
                "args": [],
                "type": "BoundingBox2d"
            }
        ],
        "values": [
            {
                "name": "centroid",
                "comment": " Get the point at the center of a bounding box.\n\n    BoundingBox2d.centroid exampleBox\n    --> Point2d.fromCoordinates ( 5.5, 4 )\n\n",
                "type": "BoundingBox2d -> Point2d"
            },
            {
                "name": "contains",
                "comment": " Check if a bounding box contains a particular point.\n\n    point =\n        Point2d.fromCoordinates ( 4, 3 )\n\n    BoundingBox2d.contains point exampleBox\n    --> True\n\n    BoundingBox2d.contains Point2d.origin exampleBox\n    --> False\n\n",
                "type": "Point2d -> BoundingBox2d -> Bool"
            },
            {
                "name": "dimensions",
                "comment": " Get the X and Y dimensions (width and height) of a bounding box.\n\n    ( width, height ) =\n        BoundingBox2d.dimensions exampleBox\n\n\n    --> width = 5\n    --> height = 4\n\n",
                "type": "BoundingBox2d -> ( Float, Float )"
            },
            {
                "name": "extrema",
                "comment": " Get the minimum and maximum X and Y values of a bounding box in a single\nrecord.\n\n    BoundingBox2d.extrema exampleBox\n    --> { minX = 3\n    --> , maxX = 8\n    --> , minY = 2\n    --> , maxY = 6\n    --> }\n\nCan be useful when combined with record destructuring, for example\n\n    { minX, maxX, minY, maxY } =\n        BoundingBox2d.extrema exampleBox\n\n\n    --> minX = 3\n    --> maxX = 8\n    --> minY = 2\n    --> maxY = 6\n\n",
                "type": "BoundingBox2d -> { minX : Float, maxX : Float, minY : Float, maxY : Float }"
            },
            {
                "name": "hull",
                "comment": " Build a bounding box that contains both given bounding boxes.\n\n    firstBox =\n        BoundingBox2d.with\n            { minX = 1\n            , maxX = 4\n            , minY = 2\n            , maxY = 3\n            }\n\n    secondBox =\n        BoundingBox2d.with\n            { minX = -2\n            , maxX = 2\n            , minY = 4\n            , maxY = 5\n            }\n\n    BoundingBox2d.hull firstBox secondBox\n    --> BoundingBox2d.with\n    -->     { minX = -2\n    -->     , maxX = 4\n    -->     , minY = 2\n    -->     , maxY = 5\n    -->     }\n\n",
                "type": "BoundingBox2d -> BoundingBox2d -> BoundingBox2d"
            },
            {
                "name": "hullOf",
                "comment": " Construct a bounding box containing all bounding boxes in the given list. If\nthe list is empty, returns `Nothing`.\n\n    singletonBox =\n        BoundingBox2d.singleton\n            (Point2d.fromCoordinates ( 1, 3 ))\n\n    BoundingBox2d.hullOf [ exampleBox, singletonBox ]\n    --> Just\n    -->     (BoundingBox2d.with\n    -->         { minX = 1,\n    -->         , maxX = 8\n    -->         , minY = 2\n    -->         , maxY = 6\n    -->         }\n    -->     )\n\n    BoundingBox2d.hullOf [ exampleBox ]\n    --> Just exampleBox\n\n    BoundingBox2d.hullOf []\n    --> Nothing\n\nIf you have exactly two bounding boxes, you can use [`BoundingBox2d.hull`](#hull)\ninstead (which returns a `BoundingBox2d` instead of a `Maybe BoundingBox2d`).\n\n",
                "type": "List BoundingBox2d -> Maybe BoundingBox2d"
            },
            {
                "name": "intersection",
                "comment": " Attempt to build a bounding box that contains all points common to both\ngiven bounding boxes. If the given boxes do not intersect, returns `Nothing`.\n\n    firstBox =\n        BoundingBox2d.with\n            { minX = 1\n            , maxX = 4\n            , minY = 2\n            , maxY = 3\n            }\n\n    secondBox =\n        BoundingBox2d.with\n            { minX = 2\n            , maxX = 5\n            , minY = 1\n            , maxY = 4\n            }\n\n    thirdBox =\n        BoundingBox2d.with\n            { minX = 1\n            , maxX = 4\n            , minY = 4\n            , maxY = 5\n            }\n\n    BoundingBox2d.intersection firstBox secondBox\n    --> Just\n    -->     (BoundingBox2d.with\n    -->         { minX = 2\n    -->         , maxX = 4\n    -->         , minY = 2\n    -->         , maxY = 3\n    -->         }\n    -->     )\n\n    BoundingBox2d.intersection firstBox thirdBox\n    --> Nothing\n\nIf two boxes just touch along an edge or at a corner, they are still considered\nto have an intersection, even though that intersection will have zero area (at\nleast one of its dimensions will be zero):\n\n    firstBox =\n        BoundingBox2d.with\n            { minX = 0\n            , maxX = 1\n            , minY = 0\n            , maxY = 2\n            }\n\n    secondBox =\n        BoundingBox2d.with\n            { minX = 1\n            , maxX = 2\n            , minY = 1\n            , maxY = 3\n            }\n\n    BoundingBox2d.intersection firstBox secondBox\n    --> Just\n    -->     (BoundingBox2d.with\n    -->         { minX = 1\n    -->         , maxX = 1\n    -->         , minY = 1\n    -->         , maxY = 2\n    -->         }\n    -->     )\n\n",
                "type": "BoundingBox2d -> BoundingBox2d -> Maybe BoundingBox2d"
            },
            {
                "name": "intersects",
                "comment": " Test if two boxes touch or overlap at all (have any points in common);\n\n    BoundingBox2d.intersects firstBox secondBox\n\nis equivalent to\n\n    BoundingBox2d.intersection firstBox secondBox\n        /= Nothing\n\nbut is more efficient.\n\n    firstBox =\n        BoundingBox2d.with\n            { minX = 0\n            , maxX = 3\n            , minY = 0\n            , maxY = 2\n            }\n\n    secondBox =\n        BoundingBox2d.with\n            { minX = 0\n            , maxX = 3\n            , minY = 1\n            , maxY = 4\n            }\n\n    thirdBox =\n        BoundingBox2d.with\n            { minX = 0\n            , maxX = 3\n            , minY = 4\n            , maxY = 5\n            }\n\n    BoundingBox2d.intersects firstBox secondBox\n    --> True\n\n    BoundingBox2d.intersects firstBox thirdBox\n    --> False\n\n",
                "type": "BoundingBox2d -> BoundingBox2d -> Bool"
            },
            {
                "name": "isContainedIn",
                "comment": " Test if the second given bounding box is fully contained within the first\n(is a subset of it).\n\n    outerBox =\n        BoundingBox2d.with\n            { minX = 0\n            , maxX = 10\n            , minY = 0\n            , maxY = 10\n            }\n\n    innerBox =\n        BoundingBox2d.with\n            { minX = 1\n            , maxX = 5\n            , minY = 3\n            , maxY = 9\n            }\n\n    overlappingBox =\n        BoundingBox2d.with\n            { minX = 1\n            , maxX = 5\n            , minY = 3\n            , maxY = 12\n            }\n\n    BoundingBox2d.isContainedIn outerBox innerBox\n    --> True\n\n    BoundingBox2d.isContainedIn outerBox overlappingBox\n    --> False\n\n",
                "type": "BoundingBox2d -> BoundingBox2d -> Bool"
            },
            {
                "name": "maxX",
                "comment": " Get the maximum X value of a bounding box.\n\n    BoundingBox2d.maxX exampleBox\n    --> 8\n\n",
                "type": "BoundingBox2d -> Float"
            },
            {
                "name": "maxY",
                "comment": " Get the maximum Y value of a bounding box.\n\n    BoundingBox2d.maxY exampleBox\n    --> 6\n\n",
                "type": "BoundingBox2d -> Float"
            },
            {
                "name": "midX",
                "comment": " Get the median X value of a bounding box.\n\n    BoundingBox2d.midX exampleBox\n    --> 5.5\n\n",
                "type": "BoundingBox2d -> Float"
            },
            {
                "name": "midY",
                "comment": " Get the median Y value of a bounding box.\n\n    BoundingBox2d.midY exampleBox\n    --> 4\n\n",
                "type": "BoundingBox2d -> Float"
            },
            {
                "name": "minX",
                "comment": " Get the minimum X value of a bounding box.\n\n    BoundingBox2d.minX exampleBox\n    --> 3\n\n",
                "type": "BoundingBox2d -> Float"
            },
            {
                "name": "minY",
                "comment": " Get the minimum Y value of a bounding box.\n\n    BoundingBox2d.minY exampleBox\n    --> 2\n\n",
                "type": "BoundingBox2d -> Float"
            },
            {
                "name": "overlappingBy",
                "comment": " Check if one box overlaps another by less than, greater than or equal to a\ngiven amount. For example, you could perform a tolerant collision check (one\nthat only returns true if the boxes overlap by at least some small finite\namount, and ignores boxes that just barely touch each other) as\n\n    boxesCollide =\n        BoundingBox2d.overlappingBy GT 0.001 box1 box2\n\nThis can be read as \"`box1` and `box2` are overlapping by greater than 0.001\nunits\". (The [`Order`](http://package.elm-lang.org/packages/elm-lang/core/latest/Basics#Order)\ntype and its three values `LT`, `GT` and `EQ` are defined in Elm's `Basics`\nmodule so are available by default in any Elm program.)\n\nOverlap is defined as the _minimum_ distance one box would have to move so that\nit did not touch the other, and is always positive for any two overlapping\nboxes.\n\nBoxes that just touch are considered to have an overlap of zero, which is\ndistinct from 'no overlap'. Boxes that do not touch or overlap at all are\nconsidered to have an overlap which is less than zero but not comparable to any\nnegative number.\n\n\n### Less than\n\n  - `overlappingBy LT 1e-3` will return true if the two boxes overlap by less\n    than 0.001 units or if they do not overlap at all (false if they overlap by\n    more than 0.001 units).\n  - `overlappingBy LT 0` will return true only if the two boxes don't touch or\n    overlap at all.\n  - `overlappingBy LT -1e-3` will always return false! If you care about _how\n    much_ two boxes are separated by, use `separatedBy` instead.\n\n\n### Greater than\n\n  - `overlappingBy GT 1e-3` will return true if the two boxes overlap by at\n    least 0.001 units (false if they overlap by less than that or do not overlap\n    at all).\n  - `overlappingBy GT 0` will return true if the two boxes overlap by any\n    non-zero amount (false if they just touch or do not overlap at all).\n  - `overlappingBy GT -1e-3` doesn't make a lot of sense but will return true if\n    the boxes touch or overlap at all (false if they don't overlap, regardless\n    of how close they are to overlapping). In this case, though, it would make\n    more sense to just user `intersects` instead.\n\n\n### Equal to\n\nChecking whether two boxes overlap by exactly a given amount is pretty weird and\nvulnerable to floating-point roundoff, but is defined as follows:\n\n  - `overlappingBy EQ 1e-3` will return true if the two boxes overlap by exactly\n    0.001 units.\n  - `overlappingBy EQ 0` will return true if and only if the boxes just touch\n    each other.\n  - `overlappingBy EQ -1e-3` will always return false.\n\n",
                "type": "Order -> Float -> BoundingBox2d -> BoundingBox2d -> Bool"
            },
            {
                "name": "overlaps",
                "comment": " DEPRECATED: Alias for `intersects`, kept for compatibility. Use `intersects`\ninstead.\n",
                "type": "BoundingBox2d -> BoundingBox2d -> Bool"
            },
            {
                "name": "scaleAbout",
                "comment": " Scale a bounding box about a given point by a given scale.\n\n    point =\n        Point2d.fromCoordinates ( 4, 4 )\n\n    BoundingBox2d.scaleAbout point 2 exampleBox\n    --> BoundingBox2d.with\n    -->     { minX = 2\n    -->     , maxX = 12\n    -->     , minY = 0\n    -->     , maxY = 8\n    -->     }\n\n",
                "type": "Point2d -> Float -> BoundingBox2d -> BoundingBox2d"
            },
            {
                "name": "separatedBy",
                "comment": " Check if one box is separated from another by less than, greater than or\nequal to a given amount. For example, to perform clash detection between some\nobjects, you could use `separatedBy` on those objects' bounding boxes as a quick\ncheck to see if the objects had a gap of at least 1 cm between them:\n\n    safelySeparated =\n        BoundingBox2d.separatedBy GT 0.01 box1 box2\n\nThis can be read as \"`box1` and `box2` are separated by greater than 0.01\nunits\". (The [`Order`](http://package.elm-lang.org/packages/elm-lang/core/latest/Basics#Order)\ntype and its three values `LT`, `GT` and `EQ` are defined in Elm's `Basics`\nmodule so are available by default in any Elm program.)\n\nSeparation is defined as the _minimum_ distance one box would have to move\nso that it touched the other, and is always positive for any two boxes that do\nnot touch.\n\nBoxes that just touch are considered to have a separation of zero, which is\ndistinct from 'no separation'. 'No separation' (overlap) is considered to be\nless than zero but not comparable to any negative number.\n\n\n### Less than\n\n  - `separatedBy LT 1e-3` will return true if the two boxes are separated by\n    less than 0.001 units or if they touch or overlap (false if they are\n    separated by at least 0.001 units).\n  - `separatedBy LT 0` will return true only if the boxes overlap by some\n    non-zero amount.\n  - `separatedBy LT -1e-3` will always return false! If you care about _how\n    much_ two boxes overlap by, use `overlappingBy` instead.\n\n\n### Greater than\n\n  - `separatedBy GT 1e-3` will return true if the two boxes are separated by at\n    least 0.001 units (false if they are separated by less than that or if they\n    touch or overlap).\n  - `separatedBy GT 0` will return true if the two boxes are separated by any\n    non-zero amount (false if they touch or overlap).\n  - `separatedBy GT -1e-3` doesn't make a lot of sense but will return true if\n    the boxes just touch or are separated by any amount (false if they overlap\n    by any non-zero amount).\n\n\n### Equal to\n\nChecking whether two boxes are separated by exactly a given amount is pretty\nweird and vulnerable to floating-point roundoff, but is defined as follows:\n\n  - `separatedBy EQ 1e-3` will return true if the two boxes are separated by\n    exactly 0.001 units.\n  - `separatedBy EQ 0` will return true if and only if the boxes just touch each\n    other.\n  - `separatedBy EQ -3` will always return false.\n\n",
                "type": "Order -> Float -> BoundingBox2d -> BoundingBox2d -> Bool"
            },
            {
                "name": "singleton",
                "comment": " Construct a zero-width bounding box containing a single point.\n\n    point =\n        Point2d.fromCoordinates ( 2, 3 )\n\n    BoundingBox2d.singleton point\n    --> BoundingBox2d.with\n    -->     { minX = 2\n    -->     , maxX = 2\n    -->     , minY = 3\n    -->     , maxY = 3\n    -->     }\n\n",
                "type": "Point2d -> BoundingBox2d"
            },
            {
                "name": "translateBy",
                "comment": " Translate a bounding box by a given displacement.\n\n    displacement =\n        Vector2d.fromComponents ( 2, -3 )\n\n    BoundingBox2d.translateBy displacement exampleBox\n    --> BoundingBox2d.with\n    -->     { minX = 5\n    -->     , maxX = 10\n    -->     , minY = -1\n    -->     , maxY = 3\n    -->     }\n\n",
                "type": "Vector2d -> BoundingBox2d -> BoundingBox2d"
            },
            {
                "name": "with",
                "comment": " Construct a bounding box from its minimum and maximum X and Y values:\n\n    exampleBox =\n        BoundingBox2d.with\n            { minX = 3\n            , maxX = 8\n            , minY = 2\n            , maxY = 6\n            }\n\nIf the minimum and maximum values are provided in the wrong order (for example\nif <code>minX&nbsp;>&nbsp;maxX</code>), then they will be swapped so that the\nresulting bounding box is valid.\n\n",
                "type": "{ minX : Float, maxX : Float, minY : Float, maxY : Float } -> BoundingBox2d"
            }
        ],
        "binops": []
    },
    {
        "name": "OpenSolid.Vector2d",
        "comment": " <img src=\"https://opensolid.github.io/images/geometry/icons/vector2d.svg\" alt=\"Vector2d\" width=\"160\">\n\nA `Vector2d` represents a quantity such as a displacement or velocity in 2D, and\nis defined by its X and Y components. This module contains a variety of\nvector-related functionality, such as\n\n  - Adding or subtracting vectors\n  - Finding the lengths of vectors\n  - Rotating vectors\n  - Converting vectors between different coordinate systems\n\nNote that unlike in many other geometry packages where vectors are used as a\ngeneral-purpose data type, OpenSolid has separate data types for vectors,\ndirections and points. In most code it is actually more common to use `Point2d`\nand `Direction2d` than `Vector2d`, and much code can avoid working directly with\n`Vector2d` values at all!\n\n@docs Vector2d\n\n\n# Constants\n\n@docs zero\n\nAlthough there are no predefined constants for the vectors with components\n(1,&nbsp;0) and (0,&nbsp;1), in most cases you will actually want their\n`Direction2d` versions [`Direction2d.x`](OpenSolid-Direction2d#x) and\n[`Direction2d.y`](OpenSolid-Direction2d#y).\n\n\n# Constructors\n\n@docs fromComponents, fromPolarComponents, from, with, perpendicularTo, interpolateFrom\n\n\n# Properties\n\n@docs components, xComponent, yComponent, polarComponents, length, squaredLength, direction, lengthAndDirection\n\n\n# Comparison\n\n@docs equalWithin\n\n\n# Measurement\n\n@docs componentIn\n\n\n# Arithmetic\n\n@docs sum, difference, dotProduct, crossProduct\n\n\n# Transformations\n\nNote that for `mirrorAcross` and `projectOnto`, only the direction of the axis\naffects the result, since vectors are position-independent. Think of\nmirroring/projecting a vector across/onto an axis as moving the vector so its\ntail is on the axis, then mirroring/projecting its tip across/onto the axis.\n\n@docs flip, normalize, scaleBy, rotateBy, mirrorAcross, projectionIn, projectOnto\n\n\n# Coordinate conversions\n\nFunctions for transforming vectors between local and global coordinates in\ndifferent coordinate frames. Like other transformations, coordinate conversions\nof vectors depend only on the orientations of the relevant frames, not the\npositions of their origin points.\n\nFor the examples, assume the following frame has been defined:\n\n    rotatedFrame =\n        Frame2d.rotateBy (degrees 30) Frame2d.xy\n\n@docs relativeTo, placeIn\n\n",
        "unions": [],
        "aliases": [
            {
                "name": "Vector2d",
                "comment": " ",
                "args": [],
                "type": "Vector2d"
            }
        ],
        "values": [
            {
                "name": "componentIn",
                "comment": " Find the component of a vector in an arbitrary direction, for example\n\n    forwardSpeed =\n        Vector2d.componentIn forwardDirection velocity\n\nThis is more general and flexible than using `xComponent` or `yComponent`, both\nof which can be expressed in terms of `componentIn`; for example,\n\n    Vector2d.xComponent vector\n\nis equivalent to\n\n    Vector2d.componentIn Direction2d.x vector\n\n",
                "type": "Direction2d -> Vector2d -> Float"
            },
            {
                "name": "components",
                "comment": " Extract the components of a vector.\n\n    Vector2d.components (Vector2d.fromComponents ( 2, 3 ))\n    --> ( 2, 3 )\n\nThis combined with Elm's built-in tuple destructuring provides a convenient way\nto extract both the X and Y components of a vector in one line of code:\n\n    ( x, y ) =\n        Vector2d.components vector\n\n",
                "type": "Vector2d -> ( Float, Float )"
            },
            {
                "name": "crossProduct",
                "comment": " Find the scalar 'cross product' of two vectors in 2D. This is defined as\n\n    crossProduct firstVector secondVector =\n        let\n            ( x1, y1 ) =\n                components firstVector\n\n            ( x2, y2 ) =\n                components secondVector\n        in\n        x1 * y2 - y1 * x2\n\nand is useful in many of the same ways as the 3D cross product:\n\n  - Its length is equal to the product of the lengths of the two given vectors\n    and the sine of the angle between them, so it can be used as a metric to\n    determine if two vectors are nearly parallel.\n  - The sign of the result indicates the direction of rotation from the first\n    vector to the second (positive indicates a counterclockwise rotation and\n    negative indicates a clockwise rotation), similar to how the direction of\n    the 3D cross product indicates the direction of rotation.\n\nSome examples:\n\n    firstVector =\n        Vector2d.fromComponents ( 2, 0 )\n\n    secondVector =\n        Vector2d.fromComponents ( 0, 3 )\n\n    Vector2d.crossProduct firstVector secondVector\n    --> 6\n\n    Vector2d.crossProduct secondVector firstVector\n    --> -6\n\n    Vector2d.crossProduct firstVector firstVector\n    --> 0\n\n",
                "type": "Vector2d -> Vector2d -> Float"
            },
            {
                "name": "difference",
                "comment": " Find the difference between two vectors (the first vector minus the second).\n\n    firstVector =\n        Vector2d.fromComponents ( 5, 6 )\n\n    secondVector =\n        Vector2d.fromComponents ( 1, 3 )\n\n    Vector2d.difference firstVector secondVector\n    --> Vector2d.fromComponents ( 4, 3 )\n\n",
                "type": "Vector2d -> Vector2d -> Vector2d"
            },
            {
                "name": "direction",
                "comment": " Attempt to find the direction of a vector. In the case of a zero vector,\nreturn `Nothing`.\n\n    Vector2d.direction (Vector2d.fromComponents ( 3, 3 ))\n    --> Just (Direction2d.fromAngle (degrees 45))\n\n    Vector2d.direction Vector2d.zero\n    --> Nothing\n\n",
                "type": "Vector2d -> Maybe Direction2d"
            },
            {
                "name": "dotProduct",
                "comment": " Find the dot product of two vectors.\n\n    firstVector =\n        Vector2d.fromComponents ( 1, 2 )\n\n    secondVector =\n        Vector2d.fromComponents ( 3, 4 )\n\n    Vector2d.dotProduct firstVector secondVector\n    --> 11\n\n",
                "type": "Vector2d -> Vector2d -> Float"
            },
            {
                "name": "equalWithin",
                "comment": " Compare two vectors within a tolerance. Returns true if the difference\nbetween the two given vectors has magnitude less than the given tolerance.\n\n    firstVector =\n        Vector2d.fromComponents ( 1, 2 )\n\n    secondVector =\n        Vector2d.fromComponents ( 0.9999, 2.0002 )\n\n    Vector2d.equalWithin 1e-3 firstVector secondVector\n    --> True\n\n    Vector2d.equalWithin 1e-6 firstVector secondVector\n    --> False\n\n",
                "type": "Float -> Vector2d -> Vector2d -> Bool"
            },
            {
                "name": "flip",
                "comment": " Reverse the direction of a vector, negating its components.\n\n    Vector2d.flip (Vector2d.fromComponents ( -1, 2 ))\n    --> Vector2d.fromComponents ( 1, -2 )\n\n",
                "type": "Vector2d -> Vector2d"
            },
            {
                "name": "from",
                "comment": " Construct a vector from the first given point to the second.\n\n    startPoint =\n        Point2d.fromCoordinates ( 1, 1 )\n\n    endPoint =\n        Point2d.fromCoordinates ( 4, 5 )\n\n    Vector2d.from startPoint endPoint\n    --> Vector2d.fromComponents ( 3, 4 )\n\n",
                "type": "Point2d -> Point2d -> Vector2d"
            },
            {
                "name": "fromComponents",
                "comment": " Construct a vector from its X and Y components.\n\n    vector =\n        Vector2d.fromComponents ( 2, 3 )\n\n",
                "type": "( Float, Float ) -> Vector2d"
            },
            {
                "name": "fromPolarComponents",
                "comment": " Construct a vector from a length and angle. The angle is measured\ncounterclockwise from the positive X direction.\n\n    Vector2d.fromPolarComponents ( 2, degrees 135 )\n    -->Vector2d.fromComponents ( -1.4142, 1.4142 )\n\n",
                "type": "( Float, Float ) -> Vector2d"
            },
            {
                "name": "interpolateFrom",
                "comment": " Construct a vector by interpolating from the first given vector to the\nsecond, based on a parameter that ranges from zero to one.\n\n    startVector =\n        Vector2d.zero\n\n    endVector =\n        Vector2d.fromComponents ( 8, 12 )\n\n    Vector2d.interpolateFrom startVector endVector 0.25\n    --> Vector2d.fromComponents ( 2, 3 )\n\nPartial application may be useful:\n\n    interpolatedVector : Float -> Vector2d\n    interpolatedVector =\n        Vector2d.interpolateFrom startVector endVector\n\n    List.map interpolatedVector [ 0, 0.5, 1 ]\n    --> [ Vector2d.fromComponents ( 0, 0 )\n    --> , Vector2d.fromComponents ( 4, 6 )\n    --> , Vector2d.fromComponents ( 8, 12 )\n    --> ]\n\nYou can pass values less than zero or greater than one to extrapolate:\n\n    interpolatedVector -0.5\n    --> Vector2d.fromComponents ( -4, -6 )\n\n    interpolatedVector 1.25\n    --> Vector2d.fromComponents ( 10, 15 )\n\n",
                "type": "Vector2d -> Vector2d -> Float -> Vector2d"
            },
            {
                "name": "length",
                "comment": " Get the length (magnitude) of a vector.\n\n    Vector2d.length (Vector2d.fromComponents ( 3, 4 ))\n    --> 5\n\n",
                "type": "Vector2d -> Float"
            },
            {
                "name": "lengthAndDirection",
                "comment": " Attempt to find the length and direction of a vector. In the case of a zero\nvector, returns `Nothing`.\n\n    vector =\n        Vector2d.fromComponents ( 1, 1 )\n\n    Vector2d.lengthAndDirection vector\n    --> Just\n    -->     ( 1.4142\n    -->     , Direction2d.fromAngle (degrees 45)\n    -->     )\n\n    Vector2d.lengthAndDirection Vector2d.zero\n    --> Nothing\n\n",
                "type": "Vector2d -> Maybe ( Float, Direction2d )"
            },
            {
                "name": "mirrorAcross",
                "comment": " Mirror a vector across a given axis.\n\n    vector =\n        Vector2d.fromComponents ( 2, 3 )\n\n    Vector2d.mirrorAcross Axis2d.y vector\n    --> Vector2d.fromComponents ( -2, 3 )\n\nThe position of the axis doesn't matter, only its orientation:\n\n    horizontalAxis =\n        Axis2d.with\n            { originPoint =\n                Point2d.fromCoordinates ( 100, 200 )\n            , direction = Direction2d.x\n            }\n\n    Vector2d.mirrorAcross horizontalAxis vector\n    --> Vector2d.fromComponents ( 2, -3 )\n\n",
                "type": "Axis2d -> Vector2d -> Vector2d"
            },
            {
                "name": "normalize",
                "comment": " Normalize a vector to have a length of one. Zero vectors are left as-is.\n\n    vector =\n        Vector2d.fromComponents ( 3, 4 )\n\n    Vector2d.normalize vector\n    --> Vector2d.fromComponents ( 0.6, 0.8 )\n\n    Vector2d.normalize Vector2d.zero\n    --> Vector2d.zero\n\n**Warning**: `Vector2d.direction` is safer since it forces you to explicitly\nconsider the case where the given vector is zero. `Vector2d.normalize` is\nprimarily useful for cases like generating WebGL meshes, where defaulting to a\nzero vector for degenerate cases is acceptable, and the overhead of something\nlike\n\n    Vector2d.direction vector\n        |> Maybe.map Direction2d.toVector\n        |> Maybe.withDefault Vector2d.zero\n\n(which is functionally equivalent to `Vector2d.normalize vector`) is too high.\n\n",
                "type": "Vector2d -> Vector2d"
            },
            {
                "name": "perpendicularTo",
                "comment": " Construct a vector perpendicular to the given vector, by rotating the given\nvector 90 degrees counterclockwise. The constructed vector will have the same\nlength as the given vector.\n\n    Vector2d.perpendicularTo\n        (Vector2d.fromComponents ( 1, 0 ))\n    --> Vector2d.fromComponents ( 0, 1 )\n\n    Vector2d.perpendicularTo\n        (Vector2d.fromComponents ( 0, 2 ))\n    --> Vector2d.fromComponents ( -2, 0 )\n\n    Vector2d.perpendicularTo\n        (Vector2d.fromComponents ( 3, 1 ))\n    --> Vector2d.fromComponents ( -1, 3 )\n\n    Vector2d.perpendicularTo Vector2d.zero\n    --> Vector2d.zero\n\n",
                "type": "Vector2d -> Vector2d"
            },
            {
                "name": "placeIn",
                "comment": " Take a vector defined in local coordinates relative to a given reference\nframe, and return that vector expressed in global coordinates.\n\n    Vector2d.fromComponents ( 2, 0 )\n        |> Vector2d.placeIn rotatedFrame\n    --> Vector2d.fromComponents ( 1.732, 1 )\n\n",
                "type": "Frame2d -> Vector2d -> Vector2d"
            },
            {
                "name": "polarComponents",
                "comment": " Get the polar components (length, polar angle) of a vector.\n\n    Vector2d.polarComponents\n        (Vector2d.fromComponents ( 1, 1 ))\n    --> ( 1.4142, degrees 45 )\n\n",
                "type": "Vector2d -> ( Float, Float )"
            },
            {
                "name": "projectOnto",
                "comment": " Project a vector onto an axis.\n\n    Vector2d.projectOnto Axis2d.y\n        (Vector2d.fromComponents ( 3, 4 ))\n    --> Vector2d.fromComponents ( 0, 4 )\n\n    Vector2d.projectOnto Axis2d.x\n        (Vector2d.fromComponents ( -1, 2 ))\n    --> Vector2d.fromComponents ( -1, 0 )\n\nThis is equivalent to finding the projection in the axis' direction.\n\n",
                "type": "Axis2d -> Vector2d -> Vector2d"
            },
            {
                "name": "projectionIn",
                "comment": " Find the projection of a vector in a particular direction. Conceptually,\nthis means splitting the original vector into a portion parallel to the given\ndirection and a portion perpendicular to it, then returning the parallel\nportion.\n\n    vector =\n        Vector2d.fromComponents ( 2, 3 )\n\n    Vector2d.projectionIn Direction2d.x vector\n    --> Vector2d.fromComponents ( 2, 0 )\n\n    Vector2d.projectionIn Direction2d.y vector\n    --> Vector2d.fromComponents ( 0, 3 )\n\n",
                "type": "Direction2d -> Vector2d -> Vector2d"
            },
            {
                "name": "relativeTo",
                "comment": " Take a vector defined in global coordinates, and return it expressed in\nlocal coordinates relative to a given reference frame.\n\n    Vector2d.fromComponents ( 2, 0 )\n        |> Vector2d.relativeTo rotatedFrame\n    --> Vector2d.fromComponents ( 1.732, -1 )\n\n",
                "type": "Frame2d -> Vector2d -> Vector2d"
            },
            {
                "name": "rotateBy",
                "comment": " Rotate a vector counterclockwise by a given angle (in radians).\n\n    Vector2d.fromComponents ( 1, 1 )\n        |> Vector2d.rotateBy (degrees 45)\n    --> Vector2d.fromComponents ( 0, 1.4142 )\n\n    Vector2d.fromComponents ( 1, 0 )\n        |> Vector2d.rotateBy pi\n    --> Vector2d.fromComponents ( -1, 0 )\n\n",
                "type": "Float -> Vector2d -> Vector2d"
            },
            {
                "name": "scaleBy",
                "comment": " Scale the length of a vector by a given scale.\n\n    Vector2d.scaleBy 3 (Vector2d.fromComponents ( 1, 2 ))\n    --> Vector2d.fromComponents ( 3, 6 )\n\n",
                "type": "Float -> Vector2d -> Vector2d"
            },
            {
                "name": "squaredLength",
                "comment": " Get the squared length of a vector. `squaredLength` is slightly faster than\n`length`, so for example\n\n    Vector2d.squaredLength vector > tolerance * tolerance\n\nis equivalent to but slightly more efficient than\n\n    Vector2d.length vector > tolerance\n\nsince the latter requires a square root under the hood. In many cases, however,\nthe speed difference will be negligible and using `length` is much more\nreadable!\n\n",
                "type": "Vector2d -> Float"
            },
            {
                "name": "sum",
                "comment": " Find the sum of two vectors.\n\n    firstVector =\n        Vector2d.fromComponents ( 1, 2 )\n\n    secondVector =\n        Vector2d.fromComponents ( 3, 4 )\n\n    Vector2d.sum firstVector secondVector\n    --> Vector2d.fromComponents ( 4, 6 )\n\n",
                "type": "Vector2d -> Vector2d -> Vector2d"
            },
            {
                "name": "with",
                "comment": " Construct a vector with the given length in the given direction.\n\n    Vector2d.with { length = 5, direction = Direction2d.y }\n    --> Vector2d.fromComponents ( 0, 5 )\n\n",
                "type": "{ length : Float, direction : Direction2d } -> Vector2d"
            },
            {
                "name": "xComponent",
                "comment": " Get the X component of a vector.\n\n    Vector2d.xComponent (Vector2d.fromComponents ( 2, 3 ))\n    --> 2\n\n",
                "type": "Vector2d -> Float"
            },
            {
                "name": "yComponent",
                "comment": " Get the Y component of a vector.\n\n    Vector2d.yComponent (Vector2d.fromComponents ( 2, 3 ))\n    --> 3\n\n",
                "type": "Vector2d -> Float"
            },
            {
                "name": "zero",
                "comment": " The zero vector.\n\n    Vector2d.zero\n    --> Vector2d.fromComponents ( 0, 0 )\n\n",
                "type": "Vector2d"
            }
        ],
        "binops": []
    },
    {
        "name": "OpenSolid.Interval",
        "comment": "\n\n@docs Interval\n\n\n# Constructors\n\n@docs with, singleton, hull, intersection, hullOf\n\n\n# Properties\n\n@docs extrema, minValue, maxValue, midpoint, width\n\n\n# Interpolation\n\n@docs interpolate\n\n\n# Arithmetic\n\n@docs sin, cos\n\n\n# Queries\n\n@docs contains, intersects, isContainedIn\n\n",
        "unions": [],
        "aliases": [
            {
                "name": "Interval",
                "comment": " Represents a bounded interval with a minimum and maximum value, for example\nthe interval from 3 to 5.\n",
                "args": [],
                "type": "Interval"
            }
        ],
        "values": [
            {
                "name": "contains",
                "comment": " Check if an interval contains a given value.\n\n    Interval.contains 0 exampleInterval\n    --> True\n\n    Interval.contains 10 exampleInterval\n    --> False\n\nThe minimum and maximum values of an interval are considered to be contained in\nthe interval, although if you are relying on this then there is a good chance\nyour code is vulnerable to numerical roundoff!\n\n    Interval.contains -1 exampleInterval\n    --> True\n\n",
                "type": "Float -> Interval -> Bool"
            },
            {
                "name": "cos",
                "comment": " Get the image of cos(x) applied on the interval.\n\n    Interval.with { minValue = -pi / 2, maxValue = pi / 2}\n        |> Interval.cos\n    --> Interval.with { minValue = 0, maxValue = 1 }\n\n",
                "type": "Interval -> Interval"
            },
            {
                "name": "extrema",
                "comment": " Get the minimum and maximum values of an interval as a single record. Useful\nwhen combined with destructuring:\n\n    { minValue, maxValue } =\n        Interval.extrema exampleInterval\n\n\n    --> minValue = -1\n    --> maxValue = 5\n\n",
                "type": "Interval -> { minValue : Float, maxValue : Float }"
            },
            {
                "name": "hull",
                "comment": " Construct an interval containing both of the given intervals.\n\n    firstInterval =\n        Interval.with { minValue = 1, maxValue = 2 }\n\n    secondInterval =\n        Interval.with { minValue = 3, maxValue = 6 }\n\n    Interval.hull firstInterval secondInterval\n    --> Interval.with { minValue = 1, maxValue = 6 }\n\n",
                "type": "Interval -> Interval -> Interval"
            },
            {
                "name": "hullOf",
                "comment": " Construct an interval containing all of the intervals in the given list. If\nthe list is empty, returns `Nothing`.\n\n    Interval.hullOf\n        [ Interval.singleton 2\n        , Interval.with { minValue = 3, maxValue = 4 }\n        ]\n    --> Just (Interval.with { minValue = 2, maxValue = 4 })\n\n    Interval.hullOf []\n    --> Nothing\n\n",
                "type": "List Interval -> Maybe Interval"
            },
            {
                "name": "interpolate",
                "comment": " Interpolate an interval from its minimum to its maximum value; a value of\n0.0 corresponds to the minimum value of the interval, a value of 0.5 corresponds\nto its midpoint and a value of 1.0 corresponds to its maximum value. Values less\nthan 0.0 or greater than 1.0 can be used to extrapolate.\n\n    Interval.interpolate 0 exampleInterval\n    --> -1\n\n    Interval.interpolate 0.75 exampleInterval\n    --> 3.5\n\n    Interval.interpolate -0.5 exampleInterval\n    --> -4\n\n",
                "type": "Float -> Interval -> Float"
            },
            {
                "name": "intersection",
                "comment": " Attempt to construct an interval containing all the values common to both\ngiven intervals. If the intervals do not intersect, returns `Nothing`.\n\n    firstInterval =\n        Interval.with { minValue = 1, maxValue = 3 }\n\n    secondInterval =\n        Interval.with { minValue = 2, maxValue = 5 }\n\n    thirdInterval =\n        Interval.with { minValue = 4, maxValue = 7 }\n\n    Interval.intersection firstInterval secondInterval\n    --> Just (Interval.with { minValue = 2, maxValue = 3 })\n\n    Interval.intersection firstInterval thirdInterval\n    --> Nothing\n\nIf the two intervals just touch, a singleton interval will be returned:\n\n    Interval.intersection\n        (Interval.with { minValue = 1, maxValue = 2 })\n        (Interval.with { minValue = 2, maxValue = 3 })\n    --> Just (Interval.with { minValue = 2, maxValue = 2})\n\n",
                "type": "Interval -> Interval -> Maybe Interval"
            },
            {
                "name": "intersects",
                "comment": " Check if two intervals touch or overlap (have any values in common).\n\n    Interval.with { minValue = 0, maxValue = 10 }\n        |> Interval.intersects exampleInterval\n    --> True\n\n    Interval.with { minValue = 10, maxValue = 20 }\n        |> Interval.intersects exampleInterval\n    --> False\n\nIntervals that just touch each other are considered to intersect (this is\nconsistent with `intersection` which will return a zero-width interval for the\nintersection of two just-touching intervals):\n\n    Interval.with { minValue = -3, maxValue = -1 }\n        |> Interval.intersects exampleInterval\n    --> True\n\nAs with `contains`, though, if you are relying on this then there is a good\nchance your code is vulnerable to numerical roundoff!\n\n",
                "type": "Interval -> Interval -> Bool"
            },
            {
                "name": "isContainedIn",
                "comment": " Check if the second interval is fully contained in the first.\n\n    -- Note that here exampleInterval is actually the\n    -- *second* interval due to how |> works\n    exampleInterval\n        |> Interval.isContainedIn\n            (Interval.with\n                { minValue = 0\n                , maxValue = 10\n                }\n            )\n    --> False\n\n    exampleInterval\n        |> Interval.isContainedIn\n            (Interval.with\n                { minValue = -10\n                , maxValue = 10\n                }\n            )\n    --> True\n\n",
                "type": "Interval -> Interval -> Bool"
            },
            {
                "name": "maxValue",
                "comment": " Get the maximum value of an interval.\n\n    Interval.maxValue exampleInterval\n    --> 5\n\n",
                "type": "Interval -> Float"
            },
            {
                "name": "midpoint",
                "comment": " Get the midpoint of an interval.\n\n    Interval.midpoint exampleInterval\n    --> 2\n\n",
                "type": "Interval -> Float"
            },
            {
                "name": "minValue",
                "comment": " Get the minimum value of an interval.\n\n    Interval.minValue exampleInterval\n    --> -1\n\n",
                "type": "Interval -> Float"
            },
            {
                "name": "sin",
                "comment": " Get the image of sin(x) applied on the interval.\n\n    Interval.with { minValue = -pi / 2, maxValue = pi / 2}\n        |> Interval.sin\n    --> Interval.with { minValue = -1, maxValue = 1 }\n\n",
                "type": "Interval -> Interval"
            },
            {
                "name": "singleton",
                "comment": " Construct a zero-width interval containing a single value.\n\n    Interval.singleton 3\n    --> Interval.with { minValue = 3, maxValue = 3 }\n\n",
                "type": "Float -> Interval"
            },
            {
                "name": "width",
                "comment": " Get the width of an interval.\n\n    Interval.width exampleInterval\n    --> 6\n\n",
                "type": "Interval -> Float"
            },
            {
                "name": "with",
                "comment": " Construct an interval with the given minimum and maximum values. They should\nbe provided in the correct order but will be flipped if necessary to result in a\nvalid interval.\n\n    exampleInterval =\n        Interval.with { minValue = -1, maxValue = 5 }\n\n",
                "type": "{ minValue : Float, maxValue : Float } -> Interval"
            }
        ],
        "binops": []
    },
    {
        "name": "OpenSolid.Scalar",
        "comment": " Convenience functions for working with scalar (floating-point) values.\n\n@docs equalWithin, interpolateFrom, hull, hullOf\n\n",
        "unions": [],
        "aliases": [],
        "values": [
            {
                "name": "equalWithin",
                "comment": " Check if two values are equal within a given tolerance.\n\n    Scalar.equalWithin 1e-6 1.9999 2.0001\n    --> False\n\n    Scalar.equalWithin 1e-3 1.9999 2.0001\n    --> True\n\n",
                "type": "Float -> Float -> Float -> Bool"
            },
            {
                "name": "hull",
                "comment": " Construct an interval containing both of the given values (which can be\ngiven in either order).\n\n    Scalar.hull 2 3\n    --> Interval.with { minValue = 2, maxValue = 3 }\n\n    Scalar.hull 5 -1\n    --> Interval.with { minValue = -1, maxValue = 5 }\n\n",
                "type": "Float -> Float -> Interval"
            },
            {
                "name": "hullOf",
                "comment": " Construct an interval containing all values in the given list. If the list\nis empty, returns `Nothing`.\n\n    Scalar.hullOf [ 2, 1, 3 ]\n    --> Just (Interval.with { minValue = 1, maxValue = 3 })\n\n    Scalar.hullOf [ -3 ]\n    --> Just (Interval.singleton -3)\n\n    Scalar.hullOf []\n    --> Nothing\n\n",
                "type": "List Float -> Maybe Interval"
            },
            {
                "name": "interpolateFrom",
                "comment": " Interpolate from the first value to the second, based on a parameter that\nranges from zero to one. Passing a parameter value of zero will return the start\nvalue and passing a parameter value of one will return the end value.\n\n    Scalar.interpolateFrom 5 10 0.5\n    --> 7.5\n\n    Scalar.interpolateFrom 2 -2 0.75\n    --> -1\n\nParameter values less than zero or greater than one can be used to extrapolate:\n\n    Scalar.interpolateFrom 5 10 1.5\n    --> 12.5\n\n    Scalar.interpolateFrom 2 -2 -0.25\n    --> 3\n\n",
                "type": "Float -> Float -> Float -> Float"
            }
        ],
        "binops": []
    }
]