[
    {
        "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 boundingBox2d, boundingBox3d\n@docs polyline2d, polyline3d, polygon2d\n@docs circle2d\n",
        "unions": [],
        "aliases": [],
        "values": [
            {
                "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": "direction2d",
                "comment": " Encode a Direction2d as a list of two floating-point components.\n",
                "type": "Direction2d -> Value"
            },
            {
                "name": "direction3d",
                "comment": " Encode a Direction3d as as a list of three floating-point components.\n",
                "type": "Direction3d -> 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`, `yDirection`\nand `zDirection` fields.\n",
                "type": "Frame3d -> Value"
            },
            {
                "name": "lineSegment2d",
                "comment": " Encode a LineSegment2d as a list of two endpoints.\n",
                "type": "LineSegment2d -> Value"
            },
            {
                "name": "lineSegment3d",
                "comment": " Encode a LineSegment3d as a list 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 as a list of two floating-point coordinates.\n",
                "type": "Point2d -> Value"
            },
            {
                "name": "point3d",
                "comment": " Encode a Point3d as as a list of three floating-point coordinates.\n",
                "type": "Point3d -> Value"
            },
            {
                "name": "polygon2d",
                "comment": " Encode a Polygon2d as a list of points.\n",
                "type": "Polygon2d -> Value"
            },
            {
                "name": "polyline2d",
                "comment": " Encode a Polyline2d as a list of points.\n",
                "type": "Polyline2d -> Value"
            },
            {
                "name": "polyline3d",
                "comment": " Encode a Polyline3d as a list of points.\n",
                "type": "Polyline3d -> Value"
            },
            {
                "name": "sketchPlane3d",
                "comment": " Encode a SketchPlane3d as an object with `originPoint`, `xDirection` and\n`yDirection` fields.\n",
                "type": "SketchPlane3d -> Value"
            },
            {
                "name": "triangle2d",
                "comment": " Encode a Triangle2d as a list of three vertices.\n",
                "type": "Triangle2d -> Value"
            },
            {
                "name": "triangle3d",
                "comment": " Encode a Triangle3d as a list of three vertices.\n",
                "type": "Triangle3d -> Value"
            },
            {
                "name": "vector2d",
                "comment": " Encode a Vector2d as a list of two floating-point components.\n",
                "type": "Vector2d -> Value"
            },
            {
                "name": "vector3d",
                "comment": " Encode a Vector3d as a list of three floating-point components.\n",
                "type": "Vector3d -> Value"
            }
        ],
        "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 connected by line segments.\nThis module contains a variety of polyline-related functionality, such as\n\n  - Computing the length of polylines\n  - Scaling, rotating, translating and mirroring polylines\n  - Converting polylines between different coordinate systems\n\nPolylines can be constructed by passing an ordered list of vertices to the\n`Polyline3d` constructor, for example\n\n    examplePolyline =\n        Polyline3d\n            [ Point2d ( 0, 0, 0 )\n            , Point2d ( 1, 0, 0 )\n            , Point2d ( 1, 2, 0 )\n            , Point2d ( 1, 2, 3 )\n            ]\n\n# Accessors\n\n@docs vertices, segments\n\n# Length\n\n@docs length\n\n# Transformations\n\nTransforming a polyline is equivalent to transforming each of its vertices.\n\n@docs scaleAbout, rotateAround, translateBy, mirrorAcross, projectOnto, map\n\n# Coordinate frames\n\n@docs relativeTo, placeIn\n\n# Sketch planes\n\n@docs projectInto\n\n# Bounds\n\n@docs boundingBox\n",
        "unions": [],
        "aliases": [],
        "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\n    -->         { minX = 0\n    -->         , maxX = 1\n    -->         , minY = 0\n    -->         , maxY = 2\n    -->         , minZ = 0\n    -->         , maxZ = 3\n    -->         }\n    -->     )\n",
                "type": "Polyline3d -> Maybe BoundingBox3d"
            },
            {
                "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",
                "type": "Polyline3d -> Float"
            },
            {
                "name": "map",
                "comment": " Transform each vertex of a polyline by the given function. All other\ntransformations can be defined in terms of `map`; for example,\n\n    Polyline3d.mirrorAcross Plane3d.xz polyline\n\nis equivalent to\n\n    Polyline3d.map (Point3d.mirrorAcross Plane3d.xz) polyline\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\n    -->     [ Point3d ( 0, 0, 0 )\n    -->     , Point3d ( 1, 0, 0 )\n    -->     , Point3d ( 1, -2, 0 )\n    -->     , Point3d ( 1, -2, 3 )\n    -->     ]\n",
                "type": "Plane3d -> Polyline3d -> 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.at (Point3d ( 1, 2, 3 ))\n\n    Polyline3d.placeIn localFrame examplePolyline\n    --> Polyline3d\n    -->     [ Point3d ( 1, 2, 3 )\n    -->     , Point3d ( 2, 2, 3 )\n    -->     , Point3d ( 2, 4, 3 )\n    -->     , Point3d ( 2, 4, 6 )\n    -->     ]\n",
                "type": "Frame3d -> Polyline3d -> Polyline3d"
            },
            {
                "name": "projectInto",
                "comment": " Project a polyline into a given sketch plane. Conceptually, this projects\nthe polyline onto the plane and then expresses the projected polyline in 2D\nsketch coordinates.\n\n    Polyline3d.projectInto Plane3d.xy examplePolyline\n    --> Polyline2d\n    -->     [ Point2d ( 0, 0 )\n    -->     , Point2d ( 1, 0 )\n    -->     , Point2d ( 1, 2 )\n    -->     , Point2d ( 1, 2 )\n    -->     ]\n",
                "type": "SketchPlane3d -> Polyline3d -> Polyline2d"
            },
            {
                "name": "projectOnto",
                "comment": " Project (flatten) a polyline onto the given plane.\n\n    Polyline3d.projectOnto Plane3d.xz examplePolyline\n    --> Polyline3d\n    -->     [ Point3d ( 0, 0, 0 )\n    -->     , Point3d ( 1, 0, 0 )\n    -->     , Point3d ( 1, 0, 0 )\n    -->     , Point3d ( 1, 0, 3 )\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.at (Point3d ( 1, 2, 3 ))\n\n    Polyline3d.relativeTo localFrame examplePolyline\n    --> Polyline3d\n    -->     [ Point3d ( -1, -2, -3 )\n    -->     , Point3d ( 0, -2, -3 )\n    -->     , Point3d ( 0, 0, -3 )\n    -->     , Point3d ( 0, 0, 0 )\n    -->     ]\n",
                "type": "Frame3d -> Polyline3d -> Polyline3d"
            },
            {
                "name": "rotateAround",
                "comment": " Rotate a polyline around the given axis by the given angle (in radians).\n\n    Polyline3d.rotateAround Axis3d.z (degrees 90) examplePolyline\n    --> Polyline3d\n    -->     [ Point3d ( 0, 0, 0 )\n    -->     , Point3d ( 0, 1, 0 )\n    -->     , Point3d ( -2, 1, 0 )\n    -->     , Point3d ( -2, 1, 3 )\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 ( 1, 0, 0 )\n\n    Polyline3d.scaleAbout point 2 examplePolyline\n    --> Polyline3d\n    -->     [ Point3d ( -1, 0, 0 )\n    -->     , Point3d ( 1, 0, 0 )\n    -->     , Point3d ( 1, 4, 0 )\n    -->     , Point3d ( 1, 4, 6 )\n    -->     ]\n",
                "type": "Point3d -> Float -> Polyline3d -> Polyline3d"
            },
            {
                "name": "segments",
                "comment": " Get the individual segments of a polyline.\n\n    Polyline3d.segments examplePolyline\n    --> [ LineSegment3d ( Point3d ( 0, 0, 0 ), Point3d ( 1, 0, 0 ) )\n    --> , LineSegment3d ( Point3d ( 1, 0, 0 ), Point3d ( 1, 2, 0 ) )\n    --> , LineSegment3d ( Point3d ( 1, 2, 0 ), Point3d ( 1, 2, 3 ) )\n    --> ]\n",
                "type": "Polyline3d -> List LineSegment3d"
            },
            {
                "name": "translateBy",
                "comment": " Translate a polyline by the given displacement.\n\n    displacement =\n        Vector3d ( 1, 2, 3 )\n\n    Polyline3d.translateBy displacement examplePolyline\n    --> Polyline3d\n    -->     [ Point3d ( 1, 2, 3 )\n    -->     , Point3d ( 2, 2, 3 )\n    -->     , Point3d ( 2, 4, 3 )\n    -->     , Point3d ( 2, 4, 6 )\n    -->     ]\n",
                "type": "Vector3d -> Polyline3d -> Polyline3d"
            },
            {
                "name": "vertices",
                "comment": " Get the vertices of a polyline.\n\n    Polyline3d.vertices examplePolyline\n    --> [ Point3d ( 0, 0, 0 )\n    --> , Point3d ( 1, 0, 0 )\n    --> , Point3d ( 1, 2, 0 )\n    --> , Point3d ( 1, 2, 3 )\n    --> ]\n",
                "type": "Polyline3d -> List Point3d"
            }
        ],
        "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\nFrames can by constructed by passing a record with `originPoint`, `xDirection`,\n`yDirection` and `zDirection` fields to the `Frame3d` constructor, for example:\n\n    frame =\n        Frame3d\n            { originPoint = Point3d ( 2, 1, 3 )\n            , xDirection = Direction3d ( 0.8, 0.6, 0 )\n            , yDirection = Direction3d ( -0.6, 0.8, 0 )\n            , zDirection = Direction3d ( 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.)\n\n# Predefined frames\n\n@docs xyz\n\n# Constructors\n\n@docs at\n\n# Accessors\n\n@docs originPoint, xDirection, yDirection, zDirection\n\n# Axes\n\n@docs xAxis, yAxis, zAxis\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\n    -->     { originPoint = Point3d.origin\n    -->     , normalDirection = Direction3d.z\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\n    -->     { originPoint = Point3d.origin\n    -->     , normalDirection = Direction3d.flip Direction3d.z\n    -->     }\n\n@docs xyPlane, yxPlane, yzPlane, zyPlane, zxPlane, xzPlane\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    Frame3d.yzSketchPlane Frame3d.xyz\n    --> SketchPlane3d\n    -->     { originPoint = Point3d.origin\n    -->     , xDirection = Direction3d.y\n    -->     , yDirection = Direction3d.z\n    -->     }\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# Transformations\n\n@docs flipX, flipY, flipZ, moveTo, rotateAround, rotateAroundOwn, translateBy, translateAlongOwn, mirrorAcross\n\n# Coordinate frames\n\n@docs relativeTo, placeIn\n",
        "unions": [],
        "aliases": [],
        "values": [
            {
                "name": "at",
                "comment": " Construct a frame aligned with the global XYZ frame but with the given\norigin point.\n\n    Frame3d.at (Point3d ( 2, 1, 3 ))\n    --> Frame3d\n    -->     { originPoint = Point3d ( 2, 1, 3 )\n    -->     , xDirection = Direction3d.x\n    -->     , yDirection = Direction3d.y\n    -->     , zDirection = Direction3d.z\n    -->     }\n",
                "type": "Point3d -> Frame3d"
            },
            {
                "name": "flipX",
                "comment": " Reverse the X direction of a frame.\n\n    Frame3d.flipX Frame3d.xyz\n    --> Frame3d\n    -->     { originPoint = Point3d.origin\n    -->     , xDirection = Direction3d.flip Direction3d.x\n    -->     , yDirection = Direction3d.y\n    -->     , zDirection = Direction3d.z\n    -->     }\n",
                "type": "Frame3d -> Frame3d"
            },
            {
                "name": "flipY",
                "comment": " Reverse the Y direction of a frame.\n\n    Frame3d.flipY Frame3d.xyz\n    --> Frame3d\n    -->     { originPoint = Point3d.origin\n    -->     , xDirection = Direction3d.x\n    -->     , yDirection = Direction3d.flip Direction3d.y\n    -->     , zDirection = Direction3d.z\n    -->     }\n",
                "type": "Frame3d -> Frame3d"
            },
            {
                "name": "flipZ",
                "comment": " Reverse the Z direction of a frame.\n\n    Frame3d.flipZ Frame3d.xyz\n    --> Frame3d\n    -->     { originPoint = Point3d.origin\n    -->     , xDirection = Direction3d.x\n    -->     , yDirection = Direction3d.y\n    -->     , zDirection = Direction3d.flip Direction3d.z\n    -->     }\n",
                "type": "Frame3d -> Frame3d"
            },
            {
                "name": "mirrorAcross",
                "comment": " Mirror a frame across a plane.\n\n    frame =\n        Frame3d.at (Point3d ( 2, 1, 3 ))\n\n    Frame3d.mirrorAcross Plane3d.xy frame\n    --> Frame3d\n    -->     { originPoint = Point3d ( 2, 1, -3 )\n    -->     , xDirection = Direction3d.x\n    -->     , yDirection = Direction3d.y\n    -->     , zDirection = Direction3d.flip Direction3d.z\n    -->     }\n\nNote that this will switch the\n[handedness](https://en.wikipedia.org/wiki/Cartesian_coordinate_system#Orientation_and_handedness)\nof the frame.\n",
                "type": "Plane3d -> Frame3d -> Frame3d"
            },
            {
                "name": "moveTo",
                "comment": " Move a frame so that it has the given origin point but same orientation.\n\n    point =\n        Point3d ( 2, 1, 3 )\n\n    Frame3d.at point\n    --> Frame3d\n    -->     { originPoint = Point3d ( 2, 1, 3 )\n    -->     , xDirection = Direction3d.x\n    -->     , yDirection = Direction3d.y\n    -->     , zDirection = Direction3d.z\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",
                "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.at (Point3d ( 2, 1, 3 ))\n\n    Frame3d.rotateAround Frame3d.zAxis (degrees 90) frame\n    --> Frame3d\n    -->     { originPoint = Point3d ( -1, 2, 3 )\n    -->     , xDirection = Direction3d.y\n    -->     , yDirection = Direction3d.flip Direction3d.x\n    -->     , zDirection = 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.at (Point3d ( 2, 1, 3 ))\n\n    Frame3d.rotateAroundOwn Frame3d.zAxis (degrees 90) frame\n    --> Frame3d\n    -->     { originPoint = Point3d ( 2, 1, 3 )\n    -->     , xDirection = Direction3d.y\n    -->     , yDirection = Direction3d.flip Direction3d.x\n    -->     , zDirection = Direction3d.z\n    -->     }\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",
                "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    Frame3d.at (Point3d ( 2, 0, 0 ))\n        |> Frame3d.rotateAroundOwn Frame3d.zAxis (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\nby 45 degrees, then translate it along its own (rotated) X axis by 2 units\",\nresulting in\n\n    Frame3d\n        { originPoint = Point3d ( 3.4142, 1.4142, 0 )\n        , xDirection = Direction3d ( 0.7071, 0.7071, 0 )\n        , yDirection = Direction3d ( -0.7071, 0.7071, 0)\n        , zDirection = 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.at (Point3d ( 2, 1, 3 ))\n\n    displacement =\n        Vector3d ( 1, 1, 1 )\n\n    Frame3d.translateBy displacement frame\n    --> Frame3d.at (Point3d ( 3, 2, 4 ))\n",
                "type": "Vector3d -> Frame3d -> 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",
                "type": "Frame3d -> Axis3d"
            },
            {
                "name": "xDirection",
                "comment": " Get the X direction of a given frame.\n\n    Frame3d.xDirection Frame3d.xyz\n    --> Direction3d.x\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.xyz\n    --> Frame3d\n    -->     { originPoint = Point3d.origin\n    -->     , xDirection = Direction3d.x\n    -->     , yDirection = Direction3d.y\n    -->     , zDirection = 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",
                "type": "Frame3d -> Axis3d"
            },
            {
                "name": "yDirection",
                "comment": " Get the Y direction of a given frame.\n\n    Frame3d.yDirection Frame3d.xyz\n    --> Direction3d.y\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",
                "type": "Frame3d -> Axis3d"
            },
            {
                "name": "zDirection",
                "comment": " Get the Z direction of a given frame.\n\n    Frame3d.zDirection Frame3d.xyz\n    --> Direction3d.z\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.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\nMany 3D data types have `projectInto` functions that return the corresponding 2D\ndata type, and those 2D data types have `placeOnto` functions for converting\nback to 3D. For example, [`Triangle3d.projectInto`](OpenSolid-Triangle3d#projectInto)\nreturns a `Triangle2d` and [`Triangle2d.placeOnto`](OpenSolid-Triangle2d#placeOnto)\nreturns a `Triangle3d`. These pairs of functions are almost, but not quite,\ninverses of each other:\n\n  - <code>Point2d.placeOnto&nbsp;sketchPlane&nbsp;>>&nbsp;Point3d.projectInto&nbsp;sketchPlane</code>\n    will just return the original `Point2d` (within roundoff error).\n  - <code>Point3d.projectInto&nbsp;sketchPlane&nbsp;>>&nbsp;Point2d.placeOnto&nbsp;sketchPlane</code>\n    is equivalent to <code>Point3d.projectOnto&nbsp;(SketchPlane3d.plane&nbsp;sketchPlane)</code>\n    since the result will always be on the given sketch plane.\n\nSketch planes can be constructed explicitly by passing a record with\n`originPoint`, `xDirection` and `yDirection` fields to the `SketchPlane3d`\nconstructor, for example\n\n    sketchPlane =\n        SketchPlane3d\n            { originPoint = Point3d ( 2, 1, 3 )\n            , xDirection = Direction3d.y\n            , yDirection = Direction3d.flip Direction3d.z\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# Predefined sketch planes\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.yz\n    --> SketchPlane3d\n    -->     { originPoint = Point3d.origin\n    -->     , xDirection = Direction3d.y\n    -->     , yDirection = Direction3d.z\n    -->     }\n\n@docs xy, yx, yz, zy, zx, xz\n\n# Accessors\n\n@docs originPoint, xDirection, yDirection, normalDirection\n\n# Axes\n\n@docs xAxis, yAxis, normalAxis\n\n# Conversions\n\n@docs plane\n\n# Transformations\n\n@docs flipX, flipY, moveTo, rotateAround, rotateAroundOwn, translateBy, translateAlongOwn, mirrorAcross\n\n# Coordinate frames\n\n@docs relativeTo, placeIn\n",
        "unions": [],
        "aliases": [],
        "values": [
            {
                "name": "flipX",
                "comment": " Flip the X direction of a sketch plane, leaving its Y direction and origin\npoint unchanged.\n\n    SketchPlane3d.flipX SketchPlane3d.yz\n    --> SketchPlane3d\n    -->     { originPoint = Point3d.origin\n    -->     , xDirection = Direction3d.flip Direction3d.y\n    -->     , yDirection = 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    SketchPlane3d.flipY SketchPlane3d.yz\n    --> SketchPlane3d\n    -->     { originPoint = Point3d.origin\n    -->     , xDirection = Direction3d.y\n    -->     , yDirection = Direction3d.flip Direction3d.z\n    -->     }\n",
                "type": "SketchPlane3d -> SketchPlane3d"
            },
            {
                "name": "mirrorAcross",
                "comment": " Mirror a sketch plane across a plane.\n\n    sketchPlane =\n        SketchPlane3d\n            { originPoint = Point2d ( 2, 1, 3 )\n            , xDirection = Direction3d.y\n            , yDirection = Direction3d.z\n            }\n\n    SketchPlane3d.mirrorAcross Plane3d.xy sketchPlane\n    --> SketchPlane3d\n    -->     { originPoint = Point2d ( 2, 1, -3 )\n    -->     , xDirection = Direction3d.y\n    -->     , yDirection = Direction3d.flip Direction3d.z\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    SketchPlane3d.moveTo (Point3d ( 2, 1, 3 )) SketchPlane3d.yz\n    --> SketchPlane3d\n    -->     { originPoint = Point3d ( 2, 1, 3 )\n    -->     , xDirection = Direction3d.y\n    -->     , yDirection = 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",
                "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.flip Direction3d.y\n",
                "type": "SketchPlane3d -> Direction3d"
            },
            {
                "name": "originPoint",
                "comment": " Get the origin point of a sketch plane.\n\n    SketchPlane3d.originPoint SketchPlane3d.xy\n    --> Point3d.origin\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": " Conver a `SketchPlane3d` to a `Plane3d` with the same origin point and\nnormal direction.\n\n    SketchPlane3d.plane SketchPlane3d.xy\n    --> Plane3d.xy\n\n    SketchPlane3d.plane SketchPlane3d.yx\n    --> Plane3d.flip Plane3d.xy\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.rotateAround Axis3d.x (degrees 90) SketchPlane3d.xy\n    --> SketchPlane3d.xz\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    SketchPlane3d.xy\n        |> SketchPlane3d.translateBy (Vector3d ( 1, 0, 0 ))\n        |> SketchPlane3d.rotateAroundOwn SketchPlane3d.yAxis (degrees -45)\n    --> SketchPlane3d\n    -->     { originPoint = Point3d ( 1, 0, 0 )\n    -->     , xDirection = Direction3d ( 0.7071, 0, 0.7071 )\n    -->     , yDirection = Direction3d.y\n    -->     }\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",
                "type": "(SketchPlane3d -> Axis3d) -> Float -> SketchPlane3d -> 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    SketchPlane3d.xy\n        |> SketchPlane3d.rotateAround Axis3d.x (degrees 45)\n        |> SketchPlane3d.translateAlongOwn SketchPlane3d.yAxis 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\n        { originPoint = Point3d ( 0, 1.4142, 1.4142 )\n        , xDirection = Direction3d.x\n        , yDirection = Direction3d ( 0, 0.7071, 0.7071 )\n        }\n",
                "type": "(SketchPlane3d -> Axis3d) -> Float -> SketchPlane3d -> SketchPlane3d"
            },
            {
                "name": "translateBy",
                "comment": " Translate a sketch plane by a given displacement.\n\n    displacement =\n        Vector3d ( 2, 1, 3 )\n\n    SketchPlane3d.translateBy displacement SketchPlane3d.xy\n    --> SketchPlane3d\n    -->     { originPoint = Point3d ( 2, 1, 3 )\n    -->     , xDirection = Direction3d.x\n    -->     , yDirection = Direction3d.y\n    -->     }\n",
                "type": "Vector3d -> SketchPlane3d -> 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",
                "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",
                "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",
                "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",
                "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.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\nPolygons can be constructed by passing an ordered list of vertices to the\n`Polygon2d` constructor, for example\n\n    rectangle =\n        Polygon2d\n            [ Point2d ( 1, 1 )\n            , Point2d ( 3, 1 )\n            , Point2d ( 3, 2 )\n            , Point2d ( 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# Accessors\n\n@docs vertices, edges\n\n# Perimeter and area\n\n@docs perimeter, area, clockwiseArea, counterclockwiseArea\n\n# Transformations\n\nTransforming a polygon is equivalent to transforming each of its vertices.\n\n@docs scaleAbout, rotateAround, translateBy, mirrorAcross, map\n\n# Coordinate frames\n\n@docs relativeTo, placeIn\n\n# Bounds\n\n@docs boundingBox\n",
        "unions": [],
        "aliases": [],
        "values": [
            {
                "name": "area",
                "comment": " Get the area of a polygon. This value will never be negative.\n\n    Polygon2d.area rectangle\n    --> 2\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\n    -->         { minX = 1\n    -->         , maxX = 3\n    -->         , minY = 1\n    -->         , maxY = 2\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",
                "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",
                "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 ( Point2d ( 1, 1 ), Point2d ( 3, 1 ) )\n    --> , LineSegment2d ( Point2d ( 3, 1 ), Point2d ( 3, 2 ) )\n    --> , LineSegment2d ( Point2d ( 3, 2 ), Point2d ( 1, 2 ) )\n    --> , LineSegment2d ( Point2d ( 1, 2 ), Point2d ( 1, 1 ) )\n    --> ]\n",
                "type": "Polygon2d -> List LineSegment2d"
            },
            {
                "name": "map",
                "comment": " Transform each vertex of a polygon by the given function. All other\ntransformations can be defined in terms of `map`; for example,\n\n    Polygon2d.mirrorAcross Axis2d.x polygon\n\nis equivalent to\n\n    Polygon2d.map (Point2d.mirrorAcross Axis2d.x) polygon\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\n    -->     [ Point2d ( 1, -1 )\n    -->     , Point2d ( 3, -1 )\n    -->     , Point2d ( 3, -2 )\n    -->     , Point2d ( 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",
                "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",
                "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.at (Point2d ( 1, 2 ))\n\n    Polygon2d.placeIn localFrame rectangle\n    --> Polygon2d\n    -->     [ Point2d ( 2, 3 )\n    -->     , Point2d ( 4, 3 )\n    -->     , Point2d ( 4, 4 )\n    -->     , Point2d ( 2, 4 )\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.at (Point2d ( 1, 2 ))\n\n    Polygon2d.relativeTo localFrame rectangle\n    --> Polygon2d\n    -->     [ Point2d ( 0, -1 )\n    -->     , Point2d ( 2, -1 )\n    -->     , Point2d ( 2, 0 )\n    -->     , Point2d ( 0, 0 )\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    Polygon2d.rotateAround Point2d.origin (degrees 90) rectangle\n    --> Polygon2d\n    -->     [ Point2d ( -1, 1 )\n    -->     , Point2d ( -1, 3 )\n    -->     , Point2d ( -2, 3 )\n    -->     , Point2d ( -2, 1 )\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 ( 2, 1 )\n\n    Polygon2d.scaleAbout point 2 rectangle\n    --> Polygon2d\n    -->     [ Point2d ( 0, 1 )\n    -->     , Point2d ( 4, 1 )\n    -->     , Point2d ( 4, 3 )\n    -->     , Point2d ( 0, 3 )\n    -->     ]\n",
                "type": "Point2d -> Float -> Polygon2d -> Polygon2d"
            },
            {
                "name": "translateBy",
                "comment": " Translate a polygon by the given displacement.\n\n    displacement =\n        Vector2d ( 2, 3 )\n\n    Polygon2d.translateBy displacement rectangle\n    --> Polygon2d\n    -->     [ Point2d ( 3, 4 )\n    -->     , Point2d ( 5, 4 )\n    -->     , Point2d ( 5, 5 )\n    -->     , Point2d ( 3, 5 )\n    -->     ]\n",
                "type": "Vector2d -> Polygon2d -> Polygon2d"
            },
            {
                "name": "vertices",
                "comment": " Get the vertices of a polygon.\n\n    Polygon2d.vertices rectangle\n    --> [ Point2d ( 1, 1 )\n    --> , Point2d ( 3, 1 )\n    --> , Point2d ( 3, 2 )\n    --> , Point2d ( 1, 2 )\n    --> ]\n",
                "type": "Polygon2d -> List Point2d"
            }
        ],
        "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 connected by line segments.\nThis module contains a variety of polyline-related functionality, such as\n\n  - Computing the length of polylines\n  - Scaling, rotating, translating and mirroring polylines\n  - Converting polylines between different coordinate systems\n\nPolylines can be constructed by passing an ordered list of vertices to the\n`Polyline2d` constructor, for example\n\n    stepShape =\n        Polyline2d\n            [ Point2d ( 0, 0 )\n            , Point2d ( 1, 0 )\n            , Point2d ( 1, 1 )\n            , Point2d ( 2, 1 )\n            ]\n\n# Accessors\n\n@docs vertices, segments\n\n# Length\n\n@docs length\n\n# Transformations\n\nTransforming a polyline is equivalent to transforming each of its vertices.\n\n@docs scaleAbout, rotateAround, translateBy, mirrorAcross, projectOnto, map\n\n# Coordinate frames\n\n@docs relativeTo, placeIn\n\n# Sketch planes\n\n@docs placeOnto\n\n# Bounds\n\n@docs boundingBox\n",
        "unions": [],
        "aliases": [],
        "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\n    -->         { minX = 0\n    -->         , maxX = 2\n    -->         , minY = 0\n    -->         , maxY = 1\n    -->         }\n    -->     )\n",
                "type": "Polyline2d -> Maybe BoundingBox2d"
            },
            {
                "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",
                "type": "Polyline2d -> Float"
            },
            {
                "name": "map",
                "comment": " Transform each vertex of a polyline by the given function. All other\ntransformations can be defined in terms of `map`; for example,\n\n    Polyline2d.mirrorAcross Axis2d.x polyline\n\nis equivalent to\n\n    Polyline2d.map (Point2d.mirrorAcross Axis2d.x) polyline\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\n    -->     [ Point2d ( 0, 0 )\n    -->     , Point2d ( 1, 0 )\n    -->     , Point2d ( 1, -1 )\n    -->     , Point2d ( 2, -1 )\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.at (Point2d ( 1, 2 ))\n\n    Polyline2d.placeIn localFrame stepShape\n    --> Polyline2d\n    -->     [ Point2d ( 1, 2 )\n    -->     , Point2d ( 2, 2 )\n    -->     , Point2d ( 2, 3 )\n    -->     , Point2d ( 3, 3 )\n    -->     ]\n",
                "type": "Frame2d -> Polyline2d -> Polyline2d"
            },
            {
                "name": "placeOnto",
                "comment": " Take a polyline defined in 2D coordinates within a particular sketch plane\nand return the corresponding polyline in 3D.\n\n    Polyline2d.placeOnto SketchPlane3d.yz stepShape\n    --> Polyline3d\n    -->     [ Point3d ( 0, 0, 0 )\n    -->     , Point3d ( 0, 1, 0 )\n    -->     , Point3d ( 0, 1, 1 )\n    -->     , Point3d ( 0, 2, 1 )\n    -->     ]\n",
                "type": "SketchPlane3d -> Polyline2d -> Polyline3d"
            },
            {
                "name": "projectOnto",
                "comment": " Project (flatten) a polyline onto the given axis.\n\n    Polyline2d.projectOnto Axis2d.x stepShape\n    --> Polyline2d\n    -->     [ Point2d ( 0, 0 )\n    -->     , Point2d ( 1, 0 )\n    -->     , Point2d ( 1, 0 )\n    -->     , Point2d ( 2, 0 )\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.at (Point2d ( 1, 2 ))\n\n    Polyline2d.relativeTo localFrame stepShape\n    --> Polyline2d\n    -->     [ Point2d ( -1, -2 )\n    -->     , Point2d ( 0, -2 )\n    -->     , Point2d ( 0, -1 )\n    -->     , Point2d ( 1, -1 )\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    Polyline2d.rotateAround Point2d.origin (degrees 90) stepShape\n    --> Polyline2d\n    -->     [ Point2d ( 0, 0 )\n    -->     , Point2d ( 0, 1 )\n    -->     , Point2d ( -1, 1 )\n    -->     , Point2d ( -1, 2 )\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 ( 1, 0 )\n\n    Polyline2d.scaleAbout point 2 stepShape\n    --> Polyline2d\n    -->     [ Point2d ( -1, 0 )\n    -->     , Point2d ( 1, 0 )\n    -->     , Point2d ( 1, 2 )\n    -->     , Point2d ( 3, 2 )\n    -->     ]\n",
                "type": "Point2d -> Float -> Polyline2d -> Polyline2d"
            },
            {
                "name": "segments",
                "comment": " Get the individual segments of a polyline.\n\n    Polyline2d.segments stepShape\n    --> [ LineSegment2d ( Point2d ( 0, 0 ), Point2d ( 1, 0 ) )\n    --> , LineSegment2d ( Point2d ( 1, 0 ), Point2d ( 1, 1 ) )\n    --> , LineSegment2d ( Point2d ( 1, 1 ), Point2d ( 2, 1 ) )\n    --> ]\n",
                "type": "Polyline2d -> List LineSegment2d"
            },
            {
                "name": "translateBy",
                "comment": " Translate a polyline by the given displacement.\n\n    displacement =\n        Vector2d ( 2, 3 )\n\n    Polyline2d.translateBy displacement stepShape\n    --> Polyline2d\n    -->     [ Point2d ( 2, 3 )\n    -->     , Point2d ( 3, 3 )\n    -->     , Point2d ( 3, 4 )\n    -->     , Point2d ( 4, 4 )\n    -->     ]\n",
                "type": "Vector2d -> Polyline2d -> Polyline2d"
            },
            {
                "name": "vertices",
                "comment": " Get the vertices of a polyline.\n\n    Polyline2d.vertices stepShape\n    --> [ Point2d ( 0, 0 )\n    --> , Point2d ( 1, 0 )\n    --> , Point2d ( 1, 1 )\n    --> , Point2d ( 2, 1 )\n    --> ]\n",
                "type": "Polyline2d -> List Point2d"
            }
        ],
        "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\nFrames can by constructed by passing a record with `originPoint`, `xDirection`\nand `yDirection` fields to the `Frame2d` constructor, for example:\n\n    frame =\n        Frame2d\n            { originPoint = Point2d ( 2, 3 )\n            , xDirection = Direction2d.fromAngle (degrees 45)\n            , yDirection = Direction2d.fromAngle (degrees 135)\n            }\n\nIn this case **you must be careful to ensure that the X and Y directions are\nperpendicular**.\n\n# Predefined frames\n\n@docs xy\n\n# Constructors\n\n@docs at\n\n# Accessors\n\n@docs originPoint, xDirection, yDirection\n\n# Axes\n\n@docs xAxis, yAxis\n\n# Transformations\n\n@docs flipX, flipY, moveTo, rotateBy, rotateAround, translateBy, translateAlongOwn, mirrorAcross\n\n# Coordinate frames\n\n@docs relativeTo, placeIn\n",
        "unions": [],
        "aliases": [],
        "values": [
            {
                "name": "at",
                "comment": " Construct a frame aligned with the global XY frame but with the given origin\npoint.\n\n    Frame2d.at (Point2d ( 2, 3 ))\n    --> Frame2d\n    -->     { originPoint = Point2d ( 2, 3 )\n    -->     , xDirection = Direction2d.x\n    -->     , yDirection = 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    Frame2d.flipX Frame2d.xy\n    --> Frame2d\n    -->     { originPoint = Point2d.origin\n    -->     , xDirection = Direction2d.flip Direction2d.x\n    -->     , yDirection = Direction2d.y\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    Frame2d.flipY Frame2d.xy\n    --> Frame2d\n    -->     { originPoint = Point2d.origin\n    -->     , xDirection = Direction2d.x\n    -->     , yDirection = Direction2d.flip Direction2d.y\n    -->     }\n",
                "type": "Frame2d -> Frame2d"
            },
            {
                "name": "mirrorAcross",
                "comment": " Mirror a frame across an axis.\n\n    frame =\n        Frame2d.at (Point2d ( 2, 3 ))\n\n    Frame2d.mirrorAcross Axis2d.x frame\n    --> Frame2d\n    -->     { originPoint = Point2d ( 2, -3 )\n    -->     , xDirection = Direction2d.x\n    -->     , yDirection = Direction2d.flip Direction2d.y\n    -->     }\n\nNote that this will switch the\n[handedness](https://en.wikipedia.org/wiki/Cartesian_coordinate_system#Orientation_and_handedness)\nof the frame.\n",
                "type": "Axis2d -> Frame2d -> Frame2d"
            },
            {
                "name": "moveTo",
                "comment": " Move a frame so that it has the given origin point.\n\n    frame =\n        Frame2d\n            { point = Point2d ( 2, 3 )\n            , xDirection = Direction2d ( 0.8, 0.6 )\n            , yDirection = Direction2d ( -0.6, 0.8 )\n            }\n\n    Frame2d.moveTo (Point2d ( 1, 1 )) frame\n    --> Frame2d\n    -->     { point = Point2d ( 1, 1 )\n    -->     , xDirection = Direction2d ( 0.8, 0.6 )\n    -->     , yDirection = Direction2d ( -0.6, 0.8 )\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",
                "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    frame =\n        Frame2d.at (Point2d ( 1, 1 ))\n\n    Frame2d.rotateAround Point2d.origin (degrees 45) frame\n    --> Frame2d\n    -->     { originPoint = Point2d ( 0, 1.4142 )\n    -->     , xDirection = Direction2d ( 0.7071, 0.7071 )\n    -->     , yDirection = Direction2d ( -0.7071, 0.7071 )\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    frame =\n        Frame2d.at (Point2d ( 1, 1 ))\n\n    Frame2d.rotateBy (degrees 45) frame\n    --> Frame2d\n    -->     { originPoint = Point2d ( 1, 1 )\n    -->     , xDirection = Direction2d ( 0.7071, 0.7071 )\n    -->     , yDirection = Direction2d ( -0.7071, 0.7071 )\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    Frame2d.at (Point2d ( 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\n        { originPoint = Point2d ( 3.4142, 1.4142 )\n        , xDirection = Direction2d ( 0.7071, 0.7071 )\n        , yDirection = Direction2d ( -0.7071, 0.7071 )\n        }\n",
                "type": "(Frame2d -> Axis2d) -> Float -> Frame2d -> Frame2d"
            },
            {
                "name": "translateBy",
                "comment": " Translate a frame by a given displacement.\n\n    frame =\n        Frame2d.at (Point2d ( 2, 3 ))\n\n    displacement =\n        Vector2d ( 1, 1 )\n\n    Frame2d.translateBy displacement frame\n    --> Frame2d.at (Point2d ( 3, 4 ))\n",
                "type": "Vector2d -> Frame2d -> 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",
                "type": "Frame2d -> Axis2d"
            },
            {
                "name": "xDirection",
                "comment": " Get the X direction of a given frame.\n\n    Frame2d.xDirection Frame2d.xy\n    --> Direction2d.x\n",
                "type": "Frame2d -> Direction2d"
            },
            {
                "name": "xy",
                "comment": " The global XY frame.\n\n    Frame2d.xy\n    --> Frame2d\n    -->     { originPoint = Point2d.origin\n    -->     , xDirection = Direction2d.x\n    -->     , yDirection = 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",
                "type": "Frame2d -> Axis2d"
            },
            {
                "name": "yDirection",
                "comment": " Get the Y direction of a given frame.\n\n    Frame2d.yDirection Frame2d.xy\n    --> Direction2d.y\n",
                "type": "Frame2d -> Direction2d"
            }
        ],
        "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\nLine segments can be constructed by passing a tuple of start and end points to\nthe `LineSegment3d` constructor, for example\n\n    exampleLineSegment =\n        LineSegment3d\n            ( Point3d ( 1, 2, 3 )\n            , Point3d ( 4, 5, 6 )\n            )\n\n# Constructors\n\n@docs along\n\n# Endpoints\n\n@docs startPoint, endPoint, endpoints, reverse\n\n# Interpolation\n\n@docs midpoint, interpolate\n\n# Length and direction\n\n@docs length, squaredLength, direction, normalDirection, vector\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 scaleAbout, rotateAround, translateBy, mirrorAcross, projectOnto, map\n\n# Coordinate frames\n\nFunctions for transforming line segments between local and global coordinates in\ndifferent coordinate frames.\n\n@docs relativeTo, placeIn\n\n# Sketch planes\n\n@docs projectInto\n\n# Bounds\n\n@docs boundingBox\n",
        "unions": [],
        "aliases": [],
        "values": [
            {
                "name": "along",
                "comment": " Construct a line segment collinear with the given axis, with its endpoints\nat the given distances from the axis' origin point.\n\n    LineSegment3d.along Axis3d.x 3 5\n    --> LineSegment3d ( Point3d ( 3, 0, 0 ), Point3d ( 5, 0, 0 ) )\n\n    LineSegment3d.along Axis3d.y 2 -4\n    --> LineSegment3d ( Point3d ( 0, 2, 0 ), Point3d ( 0, -4, 0 ) )\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\n    --     { minX = 1\n    --     , maxX = 4\n    --     , minY = 2\n    --     , maxY = 5\n    --     , minZ = 3\n    --     , maxZ = 6\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 (Direction3d ( 0.5774, 0.5774, 0.5774 ))\n",
                "type": "LineSegment3d -> Maybe Direction3d"
            },
            {
                "name": "endPoint",
                "comment": " Get the end point of a line segment.\n\n    LineSegment3d.endPoint exampleLineSegment\n    -- Point3d ( 4, 5, 6 )\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",
                "type": "LineSegment3d -> ( Point3d, Point3d )"
            },
            {
                "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. Negative values\nor values greater than 1 can be used to extrapolate.\n\n    LineSegment3d.interpolate exampleLineSegment (1 / 3)\n    -- Point3d ( 2, 4, 5 )\n\n    LineSegment3d.interpolate exampleLineSegment (-1 / 3)\n    -- Point3d ( 0, 1, 2 )\n",
                "type": "LineSegment3d -> Float -> Point3d"
            },
            {
                "name": "length",
                "comment": " Get the length of a line segment.\n\n    LineSegment3d.length exampleLineSegment\n    -- 5.1962\n",
                "type": "LineSegment3d -> Float"
            },
            {
                "name": "map",
                "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 `map`; for example,\n\n    LineSegment3d.projectOnto Plane3d.xy\n\nis equivalent to\n\n    LineSegment3d.map (Point3d.projectOnto Plane3d.xy)\n",
                "type": "(Point3d -> Point3d) -> LineSegment3d -> LineSegment3d"
            },
            {
                "name": "midpoint",
                "comment": " Get the midpoint of a line segment.\n\n    LineSegment3d.midpoint exampleLineSegment\n    -- Point3d ( 2.5, 3.5, 4.5 )\n",
                "type": "LineSegment3d -> Point3d"
            },
            {
                "name": "mirrorAcross",
                "comment": " Mirror a line segment across a plane.\n\n    LineSegment3d.mirrorAcross Plane3d.xy exampleLineSegment\n    -- LineSegment3d\n    --     ( Point3d ( 1, 2, -3 )\n    --     , Point3d ( 4, 5, -6 )\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 (Direction3d ( 0, -0.7071, 0.7071 ))\n",
                "type": "LineSegment3d -> Maybe Direction3d"
            },
            {
                "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.at (Point3d ( 1, 2, 3 ))\n\n    LineSegment3d.placeIn localFrame exampleLineSegment\n    -- LineSegment3d\n    --     ( Point3d ( 2, 4, 6 )\n    --     , Point3d ( 5, 7, 9 )\n    --     )\n",
                "type": "Frame3d -> LineSegment3d -> LineSegment3d"
            },
            {
                "name": "projectInto",
                "comment": " Project a line segment into a given sketch plane. Conceptually, this\nprojects the line segment onto the plane and then expresses the projected\nline segment in 2D sketch coordinates.\n\n    LineSegment3d.projectInto SketchPlane3d.xy exampleLineSegment\n    -- LineSegment2d\n    --     ( Point2d ( 1, 2 )\n    --     , Point2d ( 4, 5 )\n    --     )\n\n    LineSegment3d.projectInto SketchPlane3d.yz exampleLineSegment\n    -- LineSegment2d\n    --     ( Point2d ( 2, 3 )\n    --     , Point2d ( 5, 6 )\n    --     )\n\n    LineSegment3d.projectInto SketchPlane3d.zx exampleLineSegment\n    -- LineSegment2d\n    --     ( Point2d ( 3, 1 )\n    --     , Point2d ( 6, 4 )\n    --     )\n",
                "type": "SketchPlane3d -> LineSegment3d -> LineSegment2d"
            },
            {
                "name": "projectOnto",
                "comment": " Project a line segment onto a plane.\n\n    LineSegment3d.projectOnto Plane3d.yz exampleLineSegment\n    -- LineSegment3d\n    --     ( Point3d ( 0, 2, 3 )\n    --     , Point3d ( 0, 5, 6 )\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.at (Point3d ( 1, 2, 3 ))\n\n    LineSegment3d.relativeTo localFrame exampleLineSegment\n    -- LineSegment3d\n    --     ( Point3d ( 0, 0, 0 )\n    --     , Point3d ( 3, 3, 3 )\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\n    --     ( Point3d ( 4, 5, 6 )\n    --     , Point3d ( 1, 2, 3 )\n    --     )\n",
                "type": "LineSegment3d -> LineSegment3d"
            },
            {
                "name": "rotateAround",
                "comment": " Rotate around a given axis by a given angle (in radians).\n\n    LineSegment3d.rotateAround Axis3d.z (degrees 90) exampleLineSegment\n    -- LineSegment3d\n    --     ( Point3d ( -2, 1, 3 )\n    --     , Point3d ( -5, 4, 6 )\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 ( 1, 1, 1 )\n\n    LineSegment3d.scaleAbout point 2 exampleLineSegment\n    -- LineSegment3d\n    --     ( Point3d ( 1, 3, 5 )\n    --     , Point3d ( 7, 9, 11 )\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",
                "type": "LineSegment3d -> Float"
            },
            {
                "name": "startPoint",
                "comment": " Get the start point of a line segment.\n\n    LineSegment3d.startPoint exampleLineSegment\n    -- Point3d ( 1, 2, 3 )\n",
                "type": "LineSegment3d -> Point3d"
            },
            {
                "name": "translateBy",
                "comment": " Translate a line segment by a given displacement.\n\n    displacement =\n        Vector3d ( 1, 2, 3 )\n\n    LineSegment3d.translateBy displacement exampleLineSegment\n    -- LineSegment3d\n    --     ( Point3d ( 2, 4, 6 )\n    --     , Point3d ( 5, 7, 9 )\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 ( 2, 2, 2 )\n",
                "type": "LineSegment3d -> Vector3d"
            }
        ],
        "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\nPlanes can by constructed by passing a record with `originPoint` and\n`normalDirection` fields to the `Plane3d` constructor, for example:\n\n    plane =\n        Plane3d\n            { originPoint = Point3d ( 2, 1, 3 )\n            , normalDirection = Direction3d.y\n            }\n\n# Predefined planes\n\n@docs xy, yz, zx\n\n# Accessors\n\n@docs originPoint, normalDirection\n\n# Conversions\n\n@docs normalAxis, sketchPlane\n\n# Transformations\n\n@docs offsetBy, flip, rotateAround, translateBy, moveTo, mirrorAcross\n\n# Coordinate frames\n\n@docs relativeTo, placeIn\n",
        "unions": [],
        "aliases": [],
        "values": [
            {
                "name": "flip",
                "comment": " Reverse a plane's normal direction while leaving its origin point unchanged.\n\n    Plane3d.flip Plane3d.xy\n    --> Plane3d\n    -->     { originPoint = Point3d.origin\n    -->     , normalDirection = Direction3d ( 0, 0, -1 )\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\n            { originPoint = Point3d ( 1, 2, 3 )\n            , normalDirection = Direction3d.z\n            }\n\n    Plane3d.mirrorAcross Plane3d.xy plane\n    --> Plane3d\n    -->     { originPoint = Point3d ( 1, 2, -3 )\n    -->     , normalDirection = Direction3d ( 0, 0, -1 )\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 ( 1, 2, 3 )\n\n    Plane3d.moveTo newOrigin Plane3d.xy\n    --> Plane3d\n    -->     { originPoint = Point3d ( 1, 2, 3 )\n    -->     , normalDirection = Direction3d.z\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",
                "type": "Plane3d -> Axis3d"
            },
            {
                "name": "normalDirection",
                "comment": " Get the normal direction of a plane.\n\n    Plane3d.normalDirection Plane3d.xy\n    --> Direction3d.z\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\n    -->     { originPoint = Point3d ( 0, 1, 0 )\n    -->     , normalDirection = Direction3d.y\n    -->     }\n\n    Plane3d.offsetBy -2.0 Plane3d.xy\n    --> Plane3d\n    -->     { originPoint = Point3d ( 0, 0, -2 )\n    -->     , normalDirection = Direction3d.z\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",
                "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.at (Point3d ( 1, 1, 1 ))\n\n    plane =\n        Plane3d\n            { originPoint = Point3d ( 1, 2, 3 )\n            , normalDirection = Direction3d.z\n            }\n\n    Plane3d.placeIn referenceFrame plane\n    --> Plane3d\n    -->     { originPoint = Point3d ( 2, 3, 4 )\n    -->     , normalDirection = Direction3d.z\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.at (Point3d ( 1, 1, 1 ))\n\n    plane =\n        Plane3d\n            { originPoint = Point3d ( 0, 0, 2 )\n            , normalDirection = Direction3d.z\n            }\n\n    Plane3d.relativeTo referenceFrame plane\n    --> Plane3d\n    -->     { originPoint = Point3d ( -1, -1, 1 )\n    -->     , normalDirection = Direction3d.z\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",
                "type": "Axis3d -> Float -> Plane3d -> Plane3d"
            },
            {
                "name": "sketchPlane",
                "comment": " Construct a SketchPlane3d from the given plane. The origin of the sketch\nplane will be the origin point of the given plane. The X and Y basis directions\nof the sketch plane\n\n  - will be perpendicular to each other,\n  - will both be perpendicular to the normal direction of the given plane, and\n  - will have a cross product equal to the normal direction of the given plane\n\nbut are otherwise arbitrary. For example, in the current implementation,\n\n    Plane3d.sketchPlane Plane3d.xy\n    --> SketchPlane3d\n    -->     { originPoint = Point3d.origin\n    -->     , xDirection = Direction3d ( 0, -1, 0 )\n    -->     , yDirection = Direction3d ( 1, 0, 0 )\n    -->     }\n\nwhich is coplanar with and has the same origin point as [`SketchPlane3d.xy`](OpenSolid-SketchPlane3d#xy),\nbut is not equal to it as might be expected.\n\nAs a result, this function is only useful if the exact X and Y basis directions\nof the resulting sketch plane are not important; if they are, you will need to\nconstruct those directions explicitly and directly construct a new\n`SketchPlane3d` from them.\n",
                "type": "Plane3d -> SketchPlane3d"
            },
            {
                "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\n            { originPoint = Point3d ( 1, 1, 1 )\n            , normalDirection = Direction3d.z\n            }\n\n    displacement =\n        Vector3d ( 1, 2, 3 )\n\n    Plane3d.translateBy displacement plane\n    --> Plane3d\n    -->     { originPoint = Point3d ( 2, 3, 4 )\n    -->     , normalDirection = Direction3d.z\n    -->     }\n",
                "type": "Vector3d -> Plane3d -> 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\n    -->     { originPoint = Point3d.origin\n    -->     , normalDirection = Direction3d.z\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\n    -->     { originPoint = Point3d.origin\n    -->     , normalDirection = Direction3d.x\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\n    -->     { originPoint = Point3d.origin\n    -->     , normalDirection = Direction3d.y\n    -->     }\n",
                "type": "Plane3d"
            }
        ],
        "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\nAxes can by constructed by passing a record with `originPoint` and `direction`\nfields to the `Axis3d` constructor, for example:\n\n    exampleAxis =\n        Axis3d\n            { originPoint = Point3d ( -2, 1, 3 )\n            , direction = Direction3d ( 0, 0.8, -0.6 )\n            }\n\n# Predefined axes\n\n@docs x, y, z\n\n# Accessors\n\n@docs originPoint, direction\n\n# Transformations\n\n@docs flip, moveTo, rotateAround, translateBy, mirrorAcross, projectOnto\n\n# Coordinate frames\n\nFunctions for transforming axes between local and global coordinates in\ndifferent coordinate frames.\n\n@docs relativeTo, placeIn\n\n# Sketch planes\n\n@docs projectInto\n",
        "unions": [],
        "aliases": [],
        "values": [
            {
                "name": "direction",
                "comment": " Get the direction of an axis.\n\n    Axis3d.direction exampleAxis\n    --> Direction3d ( 0, 0.8, -0.6 )\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\n    -->     { originPoint = Point3d ( -2, 1, 3 )\n    -->     , direction = Direction3d ( 0, -0.8, 0.6 )\n    -->     }\n",
                "type": "Axis3d -> Axis3d"
            },
            {
                "name": "mirrorAcross",
                "comment": " Mirror an axis across a plane.\n\n    Axis3d.mirrorAcross Plane3d.xy exampleAxis\n    --> Axis3d\n    -->     { originPoint = Point3d ( -2, 1, -3 )\n    -->     , direction = Direction3d ( 0, 0.6, 0.8 )\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 ( 3, 4, 5 )\n\n    Axis3d.moveTo newOrigin exampleAxis\n    --> Axis3d\n    -->     { originPoint = Point3d ( 3, 4, 5 ),\n    -->     , direction = Direction3d ( 0, 0.8, -0.6 )\n    -->     }\n",
                "type": "Point3d -> Axis3d -> Axis3d"
            },
            {
                "name": "originPoint",
                "comment": " Get the origin point of an axis.\n\n    Axis3d.originPoint exampleAxis\n    --> Point3d ( -2, 1, 3 )\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    originPoint =\n        Point3d ( 3, 3, 3 )\n\n    Axis3d.placeIn (Frame3d.at originPoint) exampleAxis\n    --> Axis3d\n    -->     { originPoint = Point3d ( 1, 4, 6 )\n    -->     , direction = Direction3d ( 0, 0.8, -0.6 )\n    -->     }\n",
                "type": "Frame3d -> Axis3d -> Axis3d"
            },
            {
                "name": "projectInto",
                "comment": " Project an axis into a given sketch plane. Conceptually, this projects the\naxis 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.yz exampleAxis\n    --> Just\n    -->     (Axis2d\n    -->         { originPoint = Point2d ( 1, 3 )\n    -->         , direction = Direction2d ( 0.8, -0.6 )\n    -->         }\n    -->     )\n\n    Axis3d.projectInto SketchPlane3d.xy exampleAxis\n    --> Just\n    -->     (Axis2d\n    -->         { originPoint = Point2d ( -2, 1 )\n    -->         , direction = Direction3d ( 0, 1 )\n    -->         }\n    -->     )\n\n    Axis3d.projectInto SketchPlane3d.xy Axis3d.z\n    --> Nothing\n",
                "type": "SketchPlane3d -> Axis3d -> Maybe Axis2d"
            },
            {
                "name": "projectOnto",
                "comment": " Project an axis onto a plane, returning the axis that is the 'shadow' of the\ngiven axis on the given plane. If the given axis is exactly perpendicular to the\ngiven plane, returns `Nothing`.\n\n    Axis3d.projectOnto Plane3d.xy exampleAxis\n    --> Just\n    -->     (Axis3d\n    -->         { originPoint = Point3d ( -2, 1, 0 )\n    -->         , direction = Direction3d ( 0, 1, 0 )\n    -->         }\n    -->     )\n\n    Axis3d.projectOnto Plane3d.xy Axis3d.z\n    --> Nothing\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    originPoint =\n        Point3d ( 3, 3, 3 )\n\n    Axis3d.relativeTo (Frame3d.at originPoint) exampleAxis\n    --> Axis3d\n    -->     { originPoint = Point3d ( -5, -2, 0 )\n    -->     , direction = Direction3d ( 0, 0.8, -0.6 )\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\n    -->     { originPoint = Point3d ( -1, -2, 3 )\n    -->     , direction = Direction3d ( -0.8, 0, -0.6 )\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 ( 3, 3, 3 )\n\n    Axis3d.translateBy displacement exampleAxis\n    --> Axis3d\n    -->     { originPoint = Point3d ( 1, 4, 6 )\n    -->     , direction = Direction3d ( 0, 0.8, -0.6 )\n    -->     }\n",
                "type": "Vector3d -> Axis3d -> Axis3d"
            },
            {
                "name": "x",
                "comment": " The global X axis.\n\n    Axis3d.x\n    --> Axis3d\n    -->     { originPoint = Point3d.origin\n    -->     , direction = Direction3d.x\n    -->     }\n",
                "type": "Axis3d"
            },
            {
                "name": "y",
                "comment": " The global Y axis.\n\n    Axis3d.y\n    --> Axis3d\n    -->     { originPoint = Point3d.origin\n    -->     , direction = Direction3d.y\n    -->     }\n",
                "type": "Axis3d"
            },
            {
                "name": "z",
                "comment": " The global Z axis.\n\n    Axis3d.z\n    --> Axis3d\n    -->     { originPoint = Point3d.origin\n    -->     , direction = Direction3d.z\n    -->     }\n",
                "type": "Axis3d"
            }
        ],
        "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\nBounding boxes can be constructed by passing a record with `minX`, `maxX`,\n`minY`, `maxY`, `minZ` and `maxZ` fields to the `BoundingBox3d` constructor, for\nexample\n\n    exampleBox =\n        BoundingBox3d\n            { minX = -2\n            , maxX = 2\n            , minY = 2\n            , maxY = 5\n            , minZ = 3\n            , maxZ = 4\n            }\n\nIf you construct a `BoundingBox3d` this way, **you must ensure that the given\nvalues are properly ordered**: <code>minX&nbsp;<=&nbsp;maxX</code>,\n<code>minY&nbsp;<=&nbsp;maxY</code>, <code>minZ&nbsp;<=&nbsp;maxZ</code>.\nAlternately, you can construct bounding boxes using functions such as\n[`Point3d.hull`](OpenSolid-Point3d#hull) where the input order does not matter.\n\n# Constructors\n\n@docs singleton, containing\n\n# Accessors\n\n@docs extrema, minX, maxX, minY, maxY, minZ, maxZ\n@docs dimensions, midX, midY, midZ, centroid\n\n# Checks\n\n@docs contains, overlaps, isContainedIn\n\n# Boolean operations\n\n@docs hull, intersection\n",
        "unions": [],
        "aliases": [],
        "values": [
            {
                "name": "centroid",
                "comment": " Get the point at the center of a bounding box.\n\n    BoundingBox3d.centroid exampleBox\n    --> Point3d ( 0, 3.5, 3.5 )\n",
                "type": "BoundingBox3d -> Point3d"
            },
            {
                "name": "containing",
                "comment": " Construct a bounding box containing all points in the given list. If the\nlist is empty, returns `Nothing`.\n\n    points =\n        [ Point3d ( 2, 1, 3 )\n        , Point3d ( -1, 5, -2 )\n        , Point3d ( 6, 4, 2 )\n        ]\n\n    BoundingBox3d.containing points\n    --> Just\n    -->     (BoundingBox3d\n    -->         { minX = -1\n    -->         , maxX = 6\n    -->         , minY = 1\n    -->         , maxY = 5\n    -->         , minZ = -2\n    -->         , maxZ = 3\n    -->         }\n    -->     )\n\n    BoundingBox3d.containing []\n    --> Nothing\n\nIf you have exactly two points, you can use [`Point3d.hull`](OpenSolid-Point3d#hull)\ninstead (which returns a `BoundingBox3d` instead of a `Maybe BoundingBox3d`).\n",
                "type": "List Point3d -> Maybe BoundingBox3d"
            },
            {
                "name": "contains",
                "comment": " Check if a bounding box contains a particular point.\n\n    firstPoint =\n        Point3d ( 1, 4, 3 )\n\n    secondPoint =\n        Point3d ( 3, 4, 5 )\n\n    BoundingBox3d.contains firstPoint exampleBox\n    --> True\n\n    BoundingBox3d.contains secondPoint exampleBox\n    --> False\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",
                "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    --> minX = -2\n    --> maxX = 2\n    --> minY = 2\n    --> maxY = 5\n    --> minZ = 3\n    --> maxZ = 4\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\n            { minX = 1\n            , maxX = 4\n            , minY = 2\n            , maxY = 3\n            , minZ = 0\n            , maxZ = 5\n            }\n\n    secondBox =\n        BoundingBox3d\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\n    -->     { minX = -2\n    -->     , maxX = 4\n    -->     , minY = 2\n    -->     , maxY = 5\n    -->     , minZ = -1\n    -->     , maxZ = 5\n    -->     }\n",
                "type": "BoundingBox3d -> BoundingBox3d -> 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\n            { minX = 1\n            , maxX = 4\n            , minY = 2\n            , maxY = 3\n            , minZ = 5\n            , maxZ = 8\n            }\n\n    secondBox =\n        BoundingBox3d\n            { minX = 2\n            , maxX = 5\n            , minY = 1\n            , maxY = 4\n            , minZ = 6\n            , maxZ = 7\n            }\n\n    thirdBox =\n        BoundingBox3d\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\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",
                "type": "BoundingBox3d -> BoundingBox3d -> Maybe BoundingBox3d"
            },
            {
                "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\n            { minX = 0\n            , maxX = 10\n            , minY = 0\n            , maxY = 10\n            , minZ = 0\n            , maxZ = 10\n            }\n\n    innerBox =\n        BoundingBox3d\n            { minX = 1\n            , maxX = 5\n            , minY = 3\n            , maxY = 9\n            , minZ = 7\n            , maxZ = 8\n            }\n\n    overlappingBox =\n        BoundingBox3d\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",
                "type": "BoundingBox3d -> BoundingBox3d -> Bool"
            },
            {
                "name": "maxX",
                "comment": " Get the maximum X value of a bounding box.\n\n    BoundingBox3d.maxX exampleBox\n    --> 2\n",
                "type": "BoundingBox3d -> Float"
            },
            {
                "name": "maxY",
                "comment": " Get the maximum Y value of a bounding box.\n\n    BoundingBox3d.maxY exampleBox\n    --> 5\n",
                "type": "BoundingBox3d -> Float"
            },
            {
                "name": "maxZ",
                "comment": " Get the maximum Z value of a bounding box.\n\n    BoundingBox3d.maxZ exampleBox\n    --> 4\n",
                "type": "BoundingBox3d -> Float"
            },
            {
                "name": "midX",
                "comment": " Get the median X value of a bounding box.\n\n    BoundingBox3d.midX exampleBox\n    --> 0\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",
                "type": "BoundingBox3d -> Float"
            },
            {
                "name": "midZ",
                "comment": " Get the median Z value of a bounding box.\n\n    BoundingBox3d.midZ exampleBox\n    --> 3.5\n",
                "type": "BoundingBox3d -> Float"
            },
            {
                "name": "minX",
                "comment": " Get the minimum X value of a bounding box.\n\n    BoundingBox3d.minX exampleBox\n    --> -2\n",
                "type": "BoundingBox3d -> Float"
            },
            {
                "name": "minY",
                "comment": " Get the minimum Y value of a bounding box.\n\n    BoundingBox3d.minY exampleBox\n    --> 2\n",
                "type": "BoundingBox3d -> Float"
            },
            {
                "name": "minZ",
                "comment": " Get the minimum Z value of a bounding box.\n\n    BoundingBox3d.minZ exampleBox\n    --> 3\n",
                "type": "BoundingBox3d -> Float"
            },
            {
                "name": "overlaps",
                "comment": " Test if one bounding box overlaps (touches) another.\n\n    firstBox =\n        BoundingBox3d\n            { minX = 0\n            , maxX = 3\n            , minY = 0\n            , maxY = 2\n            , minZ = 0\n            , maxZ = 1\n            }\n\n    secondBox =\n        BoundingBox3d\n            { minX = 0\n            , maxX = 3\n            , minY = 1\n            , maxY = 4\n            , minZ = -1\n            , maxZ = 2\n            }\n\n    thirdBox =\n        BoundingBox3d\n            { minX = 0\n            , maxX = 3\n            , minY = 4\n            , maxY = 5\n            , minZ = -1\n            , maxZ = 2\n            }\n\n    BoundingBox3d.overlaps firstBox secondBox\n    --> True\n\n    BoundingBox3d.overlaps firstBox thirdBox\n    --> False\n",
                "type": "BoundingBox3d -> BoundingBox3d -> Bool"
            },
            {
                "name": "singleton",
                "comment": " Construct a zero-width bounding box containing a single point.\n\n    point =\n        Point3d ( 2, 1, 3 )\n\n    BoundingBox3d.singleton point\n    --> BoundingBox3d\n    -->     { minX = 2\n    -->     , maxX = 2\n    -->     , minY = 1\n    -->     , maxY = 1\n    -->     , minZ = 3\n    -->     , maxZ = 3\n    -->     }\n",
                "type": "Point3d -> BoundingBox3d"
            }
        ],
        "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\nTriangles can be constructed by passing a tuple of vertices to the `Triangle3d`\nconstructor, for example\n\n    exampleTriangle =\n        Triangle3d\n            ( Point3d ( 1, 0, 0 )\n            , Point3d ( 2, 0, 0 )\n            , Point3d ( 2, 1, 3 )\n            )\n\n# Accessors\n\n@docs vertices, edges\n\n# Basics\n\n@docs centroid, area\n\n# Transformations\n\nTransforming a triangle is equivalent to transforming its vertices.\n\n@docs scaleAbout, rotateAround, translateBy, mirrorAcross, projectOnto, map\n\n# Coordinate frames\n\nFunctions for transforming triangles between local and global coordinates in\ndifferent coordinate frames.\n\n@docs relativeTo, placeIn\n\n# Sketch planes\n\n@docs projectInto\n\n# Bounds\n\n@docs boundingBox\n",
        "unions": [],
        "aliases": [],
        "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\n    -->     { minX = 1\n    -->     , maxX = 2\n    -->     , minY = 0\n    -->     , maxY = 1\n    -->     , minZ = 0\n    -->     , maxZ = 3\n    -->     }\n",
                "type": "Triangle3d -> BoundingBox3d"
            },
            {
                "name": "centroid",
                "comment": " Get the centroid (center of mass) of a triangle.\n\n    Triangle3d.centroid exampleTriangle\n    --> Point3d ( 1.6667, 0.6667, 1 )\n",
                "type": "Triangle3d -> Point3d"
            },
            {
                "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    --> e1 = LineSegment3d ( Point3d ( 1, 0, 0 ), Point3d ( 2, 0, 0 ) )\n    --> e2 = LineSegment3d ( Point3d ( 2, 0, 0 ), Point3d ( 2, 1, 3 ) )\n    --> e3 = LineSegment3d ( Point3d ( 2, 1, 3 ), Point3d ( 1, 0, 0 ) )\n",
                "type": "Triangle3d -> ( LineSegment3d, LineSegment3d, LineSegment3d )"
            },
            {
                "name": "map",
                "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 `map`; for example,\n\n    Triangle.projectOnto Plane3d.xz triangle\n\nis equivalent to\n\n    Triangle.map (Point3d.projectOnto Plane3d.xz) triangle\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\n    -->     ( Point3d ( -1, 0, 0 )\n    -->     ( Point3d ( -2, 0, 0 )\n    -->     ( Point3d ( -2, 1, 3 )\n    -->     )\n",
                "type": "Plane3d -> Triangle3d -> 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.at (Point3d ( 2, 1, 3 ))\n\n    Triangle3d.placeIn localFrame exampleTriangle\n    --> Triangle3d\n    -->     ( Point3d ( 3, 1, 3 )\n    -->     , Point3d ( 4, 1, 3 )\n    -->     , Point3d ( 4, 2, 6 )\n    -->     )\n",
                "type": "Frame3d -> Triangle3d -> Triangle3d"
            },
            {
                "name": "projectInto",
                "comment": " Project a triangle into a given sketch plane. Conceptually, this projects\nthe triangle onto the plane and then expresses the projected triangle in 2D\nsketch coordinates.\n\n    Triangle3d.projectInto SketchPlane3d.xy exampleTriangle\n    --> Triangle2d\n    -->     ( Point2d ( 1, 0 )\n    -->     , Point2d ( 2, 0 )\n    -->     , Point2d ( 2, 1 )\n    -->     )\n\n    Triangle3d.projectInto SketchPlane3d.zx exampleTriangle\n    --> Triangle2d\n    -->     ( Point2d ( 0, 1 )\n    -->     , Point2d ( 0, 2 )\n    -->     , Point2d ( 3, 2 )\n    -->     )\n",
                "type": "SketchPlane3d -> Triangle3d -> Triangle2d"
            },
            {
                "name": "projectOnto",
                "comment": " Project a triangle onto a given plane.\n\n    Triangle3d.projectOnto Plane3d.xy exampleTriangle\n    --> Triangle3d\n    -->     ( Point3d ( 1, 0, 0 )\n    -->     , Point3d ( 2, 0, 0 )\n    -->     , Point3d ( 2, 1, 0 )\n    -->     )\n\n    Triangle3d.projectOnto Plane3d.xz exampleTriangle\n    --> Triangle3d\n    -->     ( Point3d ( 1, 0, 0 )\n    -->     , Point3d ( 2, 0, 0 )\n    -->     , Point3d ( 2, 0, 3 )\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.at (Point3d ( 2, 1, 3 ))\n\n    Triangle3d.relativeTo localFrame exampleTriangle\n    --> Triangle3d\n    -->     ( Point3d ( -1, -1, -3 )\n    -->     , Point3d ( 0, -1, -3 )\n    -->     , Point3d ( 0, 0, 0 )\n    -->     )\n",
                "type": "Frame3d -> Triangle3d -> Triangle3d"
            },
            {
                "name": "rotateAround",
                "comment": " Rotate a triangle around a given axis by a given angle (in radians).\n\n    Triangle3d.rotateAround Axis3d.z (degrees 90) exampleTriangle\n    --> Triangle3d\n    -->     ( Point3d ( 0, 1, 0 )\n    -->     , Point3d ( 0, 2, 0 )\n    -->     , Point3d ( -1, 2, 3 )\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\n    -->     ( Point3d ( 2, 0, 0 )\n    -->     , Point3d ( 4, 0, 0 )\n    -->     , Point3d ( 4, 2, 6 )\n    -->     )\n",
                "type": "Point3d -> Float -> Triangle3d -> Triangle3d"
            },
            {
                "name": "translateBy",
                "comment": " Translate a triangle by a given displacement.\n\n    displacement =\n        Vector3d ( 2, -1, 3 )\n\n    Triangle3d.translateBy displacement exampleTriangle\n    --> Triangle3d\n    -->     ( Point3d ( 3, -1, 3 )\n    -->     , Point3d ( 4, -1, 3 )\n    -->     , Point3d ( 4, 0, 6 )\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    --> p1 = Point3d ( 1, 0, 0 )\n    --> p2 = Point3d ( 2, 0, 0 )\n    --> p3 = Point3d ( 2, 1, 3 )\n",
                "type": "Triangle3d -> ( Point3d, Point3d, Point3d )"
            }
        ],
        "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\nBounding boxes can be constructed by passing a record with `minX`, `maxX`,\n`minY` and `maxY` fields to the `BoundingBox2d` constructor, for example\n\n    exampleBox =\n        BoundingBox2d\n            { minX = 3\n            , maxX = 8\n            , minY = 2\n            , maxY = 6\n            }\n\nIf you construct a `BoundingBox2d` this way, **you must ensure that the given\nvalues are properly ordered**: <code>minX&nbsp;<=&nbsp;maxX</code>,\n<code>minY&nbsp;<=&nbsp;maxY</code>. Alternately, you can construct bounding\nboxes using functions such as [`Point2d.hull`](OpenSolid-Point2d#hull) where the\ninput order does not matter.\n\n# Constructors\n\n@docs singleton, containing\n\n# Accessors\n\n@docs extrema, minX, maxX, minY, maxY\n@docs dimensions, midX, midY, centroid\n\n# Checks\n\n@docs contains, overlaps, isContainedIn\n\n# Boolean operations\n\n@docs hull, intersection\n",
        "unions": [],
        "aliases": [],
        "values": [
            {
                "name": "centroid",
                "comment": " Get the point at the center of a bounding box.\n\n    BoundingBox2d.centroid exampleBox\n    --> Point2d ( 5.5, 4 )\n",
                "type": "BoundingBox2d -> Point2d"
            },
            {
                "name": "containing",
                "comment": " Construct a bounding box containing all points in the given list. If the\nlist is empty, returns `Nothing`.\n\n    points =\n        [ Point2d ( 2, 3 )\n        , Point2d ( -1, 5 )\n        , Point2d ( 6, 4 )\n        ]\n\n    BoundingBox2d.containing points\n    --> Just\n    -->     (BoundingBox2d\n    -->         { minX = -1\n    -->         , maxX = 6\n    -->         , minY = 3\n    -->         , maxY = 5\n    -->         }\n    -->     )\n\n    BoundingBox2d.containing []\n    --> Nothing\n\nIf you have exactly two points, you can use [`Point2d.hull`](OpenSolid-Point2d#hull)\ninstead (which returns a `BoundingBox2d` instead of a `Maybe BoundingBox2d`).\n",
                "type": "List Point2d -> Maybe BoundingBox2d"
            },
            {
                "name": "contains",
                "comment": " Check if a bounding box contains a particular point.\n\n    BoundingBox2d.contains (Point2d ( 4, 3 )) exampleBox\n    --> True\n\n    BoundingBox2d.contains Point2d.origin exampleBox\n    --> False\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    --> width = 5\n    --> height = 4\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    --> minX = 3\n    --> maxX = 8\n    --> minY = 2\n    --> maxY = 6\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\n            { minX = 1\n            , maxX = 4\n            , minY = 2\n            , maxY = 3\n            }\n\n    secondBox =\n        BoundingBox2d\n            { minX = -2\n            , maxX = 2\n            , minY = 4\n            , maxY = 5\n            }\n\n    BoundingBox2d.hull firstBox secondBox\n    --> BoundingBox2d\n    -->     { minX = -2\n    -->     , maxX = 4\n    -->     , minY = 2\n    -->     , maxY = 5\n    -->     }\n",
                "type": "BoundingBox2d -> BoundingBox2d -> 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 overlap, returns `Nothing`.\n\n    firstBox =\n        BoundingBox2d\n            { minX = 1\n            , maxX = 4\n            , minY = 2\n            , maxY = 3\n            }\n\n    secondBox =\n        BoundingBox2d\n            { minX = 2\n            , maxX = 5\n            , minY = 1\n            , maxY = 4\n            }\n\n    thirdBox =\n        BoundingBox2d\n            { minX = 1\n            , maxX = 4\n            , minY = 4\n            , maxY = 5\n            }\n\n    BoundingBox2d.intersection firstBox secondBox\n    --> Just\n    -->     (BoundingBox2d\n    -->         { minX = 2\n    -->         , maxX = 4\n    -->         , minY = 2\n    -->         , maxY = 3\n    -->         }\n    -->     )\n\n    BoundingBox2d.intersection firstBox thirdBox\n    --> Nothing\n",
                "type": "BoundingBox2d -> BoundingBox2d -> Maybe BoundingBox2d"
            },
            {
                "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\n            { minX = 0\n            , maxX = 10\n            , minY = 0\n            , maxY = 10\n            }\n\n    innerBox =\n        BoundingBox2d\n            { minX = 1\n            , maxX = 5\n            , minY = 3\n            , maxY = 9\n            }\n\n    overlappingBox =\n        BoundingBox2d\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",
                "type": "BoundingBox2d -> BoundingBox2d -> Bool"
            },
            {
                "name": "maxX",
                "comment": " Get the maximum X value of a bounding box.\n\n    BoundingBox2d.maxX exampleBox\n    --> 8\n",
                "type": "BoundingBox2d -> Float"
            },
            {
                "name": "maxY",
                "comment": " Get the maximum Y value of a bounding box.\n\n    BoundingBox2d.maxY exampleBox\n    --> 6\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",
                "type": "BoundingBox2d -> Float"
            },
            {
                "name": "midY",
                "comment": " Get the median Y value of a bounding box.\n\n    BoundingBox2d.midY exampleBox\n    --> 4\n",
                "type": "BoundingBox2d -> Float"
            },
            {
                "name": "minX",
                "comment": " Get the minimum X value of a bounding box.\n\n    BoundingBox2d.minX exampleBox\n    --> 3\n",
                "type": "BoundingBox2d -> Float"
            },
            {
                "name": "minY",
                "comment": " Get the minimum Y value of a bounding box.\n\n    BoundingBox2d.minY exampleBox\n    --> 2\n",
                "type": "BoundingBox2d -> Float"
            },
            {
                "name": "overlaps",
                "comment": " Test if one bounding box overlaps (touches) another.\n\n    firstBox =\n        BoundingBox2d\n            { minX = 0\n            , maxX = 3\n            , minY = 0\n            , maxY = 2\n            }\n\n    secondBox =\n        BoundingBox2d\n            { minX = 0\n            , maxX = 3\n            , minY = 1\n            , maxY = 4\n            }\n\n    thirdBox =\n        BoundingBox2d\n            { minX = 0\n            , maxX = 3\n            , minY = 4\n            , maxY = 5\n            }\n\n    BoundingBox2d.overlaps firstBox secondBox\n    --> True\n\n    BoundingBox2d.overlaps firstBox thirdBox\n    --> False\n",
                "type": "BoundingBox2d -> BoundingBox2d -> Bool"
            },
            {
                "name": "singleton",
                "comment": " Construct a zero-width bounding box containing a single point.\n\n    point =\n        Point2d ( 2, 3 )\n\n    BoundingBox2d.singleton point\n    --> BoundingBox2d\n    -->     { minX = 2\n    -->     , maxX = 2\n    -->     , minY = 3\n    -->     , maxY = 3\n    -->     }\n",
                "type": "Point2d -> BoundingBox2d"
            }
        ],
        "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\nAxes can by constructed by passing a record with `originPoint` and `direction`\nfields to the `Axis2d` constructor, for example:\n\n    exampleAxis =\n        Axis2d\n            { originPoint = Point2d ( 1, 3 )\n            , direction = Direction2d ( 0.8, 0.6 )\n            }\n\n# Predefined axes\n\n@docs x, y\n\n# Accessors\n\n@docs originPoint, direction\n\n# Transformations\n\n@docs flip, moveTo, rotateAround, translateBy, mirrorAcross\n\n# Coordinate frames\n\nFunctions for transforming axes between local and global coordinates in\ndifferent coordinate frames.\n\n@docs relativeTo, placeIn\n\n# Sketch planes\n\n@docs placeOnto\n",
        "unions": [],
        "aliases": [],
        "values": [
            {
                "name": "direction",
                "comment": " Get the direction of an axis.\n\n    Axis2d.direction exampleAxis\n    --> Direction2d ( 0.8, 0.6 )\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\n    -->     { originPoint = Point2d ( 1, 3 )\n    -->     , direction = Direction2d ( -0.8, -0.6 )\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\n    -->     { originPoint = Point2d ( 1, -3 )\n    -->     , direction = Direction2d ( 0.8, -0.6 )\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 ( 4, 5 )\n\n    Axis2d.moveTo newOrigin exampleAxis\n    --> Axis2d\n    -->     { originPoint = Point2d ( 4, 5 )\n    -->     , direction = Direction2d ( 0.8, 0.6 )\n    -->     }\n",
                "type": "Point2d -> Axis2d -> Axis2d"
            },
            {
                "name": "originPoint",
                "comment": " Get the origin point of an axis.\n\n    Axis2d.originPoint exampleAxis\n    --> Point2d ( 1, 3 )\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    originPoint =\n        Point2d ( 2, 3 )\n\n    Axis2d.placeIn (Frame2d.at originPoint) exampleAxis\n    --> Axis2d\n    -->     { originPoint = Point2d ( 3, 6 )\n    -->     , direction = Direction2d ( 0.8, 0.6 )\n    -->     }\n",
                "type": "Frame2d -> Axis2d -> Axis2d"
            },
            {
                "name": "placeOnto",
                "comment": " Take an axis defined in 2D coordinates within a particular sketch plane and\nreturn the corresponding axis in 3D.\n\n    Axis2d.placeOnto SketchPlane3d.xy exampleAxis\n    --> Axis3d\n    -->     { originPoint = Point3d ( 2, 3, 0 )\n    -->     , direction = Direction3d ( 0.8, 0.6, 0 )\n    -->     }\n\n    Axis2d.placeOnto SketchPlane3d.zx exampleAxis\n    --> Axis3d\n    -->     { originPoint = Point3d ( 3, 0, 2 )\n    -->     , direction = Direction3d ( 0.6, 0, 0.8 )\n    -->     }\n",
                "type": "SketchPlane3d -> Axis2d -> 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    originPoint =\n        Point2d ( 2, 3 )\n\n    Axis2d.relativeTo (Frame2d.at originPoint) exampleAxis\n    --> Axis2d\n    -->     { originPoint = Point2d ( -1, 0 )\n    -->     , direction = Direction2d ( 0.8, 0.6 )\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 (degrees 90) exampleAxis\n    --> Axis2d\n    -->     { originPoint = Point2d ( -3, 1 )\n    -->     , direction = Direction2d ( -0.6, 0.8 )\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 ( 2, 3 )\n\n    Axis2d.translateBy displacement exampleAxis\n    --> Axis2d\n    -->     { originPoint = Point2d ( 3, 6 )\n    -->     , direction = Direction2d ( 0.8, 0.6 )\n    -->     }\n",
                "type": "Vector2d -> Axis2d -> Axis2d"
            },
            {
                "name": "x",
                "comment": " The global X axis.\n\n    Axis2d.x\n    --> Axis2d\n    -->     { originPoint = Point2d.origin\n    -->     , direction = Direction2d.x\n    -->     }\n",
                "type": "Axis2d"
            },
            {
                "name": "y",
                "comment": " The global Y axis.\n\n    Axis2d.y\n    --> Axis2d\n    -->     { originPoint = Point2d.origin\n    -->     , direction = Direction2d.y\n    -->     }\n",
                "type": "Axis2d"
            }
        ],
        "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. Currently you can only\ndo a few basic things with circles, such as measuring the area or checking if a\nparticular point is contained, but this should increase in the future.\n\nCircles can be constructed by passing a record with `centerPoint` and `radius`\nfields to the `Circle2d` constructor, for example\n\n    exampleCircle =\n        Circle2d\n            { centerPoint = Point2d ( 1, 2 )\n            , radius = 3\n            }\n\n**You must ensure the provided radius is positive** (or zero, but that's not a\nvery useful circle).\n\n# Accessors\n\n@docs centerPoint, radius, diameter, area, circumference\n\n# Queries\n\n@docs contains\n\n# Transformations\n\n@docs scaleAbout, rotateAround, translateBy, mirrorAcross\n\n# Coordinate transformations\n\n@docs relativeTo, placeIn\n\n# Bounds\n\n@docs boundingBox\n",
        "unions": [],
        "aliases": [],
        "values": [
            {
                "name": "area",
                "comment": " Get the area of a circle.\n\n    Circle2d.area exampleCircle\n    --> 28.2743\n",
                "type": "Circle2d -> Float"
            },
            {
                "name": "boundingBox",
                "comment": " Get the minimal bounding box containing a given circle.\n\n    Circle2d.boundingBox exampleCircle\n    --> BoundingBox2d\n    -->     { minX = -2\n    -->     , maxX = 4\n    -->     , minY = -1\n    -->     , maxY = 5\n    -->     }\n",
                "type": "Circle2d -> BoundingBox2d"
            },
            {
                "name": "centerPoint",
                "comment": " Get the center point of a circle.\n\n    Circle2d.centerPoint exampleCircle\n    --> Point2d ( 1, 2 )\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    Circle2d.contains (Point2d ( 10, 10 )) exampleCircle\n    --> False\n",
                "type": "Point2d -> Circle2d -> Bool"
            },
            {
                "name": "diameter",
                "comment": " Get the diameter of a circle.\n\n    Circle2d.diameter exampleCircle\n    --> 6\n",
                "type": "Circle2d -> Float"
            },
            {
                "name": "mirrorAcross",
                "comment": " Mirror a circle across a given axis.\n\n    Circle2d.mirrorAcross Axis2d.x exampleCircle\n    --> Circle2d\n    -->     { centerPoint = Point2d ( 1, -2 )\n    -->     , radius = 3\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.at (Point2d ( 2, 3 ))\n\n    Circle2d.placeIn localFrame exampleCircle\n    --> Circle2d\n    -->     { centerPoint = Point2d ( 3, 5 )\n    -->     , radius = 3\n    -->     }\n",
                "type": "Frame2d -> Circle2d -> Circle2d"
            },
            {
                "name": "radius",
                "comment": " Get the radius of a circle.\n\n    Circle2d.radius exampleCircle\n    --> 3\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.at (Point2d ( 2, 3 ))\n\n    Circle2d.relativeTo localFrame exampleCircle\n    --> Circle2d\n    -->     { centerPoint = Point2d ( -1, -1 )\n    -->     , radius = 3\n    -->     }\n",
                "type": "Frame2d -> Circle2d -> Circle2d"
            },
            {
                "name": "rotateAround",
                "comment": " Rotate a circle around a given point by a given angle (in radians).\n\n    Circle2d.rotateAround Point2d.origin (degrees 90) exampleCircle\n    --> Circle2d\n    -->     { centerPoint = Point2d ( -2, 1 )\n    -->     , radius = 3\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\n    -->     { centerPoint = Point2d ( 2, 4 )\n    -->     , radius = 6\n    -->     }\n\n    Circle2d.scaleAbout (Point2d ( 1, 2 )) 0.5 exampleCircle\n    --> Circle2d\n    -->     { centerPoint = Point2d ( 1, 2 )\n    -->     , radius = 1.5\n    -->     }\n",
                "type": "Point2d -> Float -> Circle2d -> Circle2d"
            },
            {
                "name": "translateBy",
                "comment": " Translate a circle by a given displacement.\n\n    Circle2d.translateBy (Vector2d ( 2, 2 )) exampleCircle\n    --> Circle2d\n    -->     { centerPoint = Point2d ( 3, 4 )\n    -->     , radius = 3\n    -->     }\n",
                "type": "Vector2d -> Circle2d -> Circle2d"
            }
        ],
        "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\nTriangles can be constructed by passing a tuple of vertices to the `Triangle2d`\nconstructor, for example\n\n    exampleTriangle =\n        Triangle2d\n            ( Point2d ( 1, 1 )\n            , Point2d ( 2, 1 )\n            , Point2d ( 1, 3 )\n            )\n\n# Accessors\n\n@docs vertices, edges\n\n# Basics\n\n@docs centroid, contains\n\n# Area\n\n@docs area, counterclockwiseArea, clockwiseArea\n\n# Transformations\n\nTransforming a triangle is equivalent to transforming its vertices.\n\n@docs scaleAbout, rotateAround, translateBy, mirrorAcross, map\n\n# Coordinate frames\n\nFunctions for transforming triangles between local and global coordinates in\ndifferent coordinate frames.\n\n@docs relativeTo, placeIn\n\n# Sketch planes\n\n@docs placeOnto\n\n# Bounds\n\n@docs boundingBox\n",
        "unions": [],
        "aliases": [],
        "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",
                "type": "Triangle2d -> Float"
            },
            {
                "name": "boundingBox",
                "comment": " Get the minimal bounding box containing a given triangle.\n\n    Triangle2d.boundingBox exampleTriangle\n    --> BoundingBox2d\n    -->     { minX = 1\n    -->     , maxX = 2\n    -->     , minY = 1\n    -->     , maxY = 3\n    -->     }\n",
                "type": "Triangle2d -> BoundingBox2d"
            },
            {
                "name": "centroid",
                "comment": " Get the centroid (center of mass) of a triangle.\n\n    Triangle2d.centroid exampleTriangle\n    --> Point2d ( 1.3333, 1.6667 )\n",
                "type": "Triangle2d -> Point2d"
            },
            {
                "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",
                "type": "Triangle2d -> Float"
            },
            {
                "name": "contains",
                "comment": " Check whether a given point is inside a given triangle.\n\n    interiorPoint =\n        Point2d ( 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",
                "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",
                "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    --> e1 = LineSegment2d ( Point2d ( 1, 1 ), Point2d ( 2, 1 ) )\n    --> e2 = LineSegment2d ( Point2d ( 2, 1 ), Point2d ( 1, 3 ) )\n    --> e3 = LineSegment2d ( Point2d ( 1, 3 ), Point2d ( 1, 1 ) )\n",
                "type": "Triangle2d -> ( LineSegment2d, LineSegment2d, LineSegment2d )"
            },
            {
                "name": "map",
                "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 `map`; for example,\n\n    Triangle.mirrorAcross Axis2d.x triangle\n\nis equivalent to\n\n    Triangle.map (Point2d.mirrorAcross Axis2d.x) triangle\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\n    -->     ( Point2d ( -1, 1 )\n    -->     , Point2d ( -2, 1 )\n    -->     , Point2d ( -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",
                "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.at (Point2d ( 1, 2 ))\n\n    Triangle2d.placeIn localFrame exampleTriangle\n    --> Triangle2d\n    -->     ( Point2d ( 2, 3 )\n    -->     , Point2d ( 3, 3 )\n    -->     , Point2d ( 2, 5 )\n    -->     )\n",
                "type": "Frame2d -> Triangle2d -> Triangle2d"
            },
            {
                "name": "placeOnto",
                "comment": " Take a triangle defined in 2D coordinates within a particular sketch\nplane and return the corresponding triangle in 3D.\n\n    Triangle2d.placeOnto SketchPlane3d.xz exampleTriangle\n    --> Triangle3d\n    -->     ( Point3d ( 1, 0, 1 )\n    -->     , Point3d ( 2, 0, 1 )\n    -->     , Point3d ( 1, 0, 3 )\n    -->     )\n",
                "type": "SketchPlane3d -> Triangle2d -> 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        Frame2d.at (Point2d ( 1, 2 ))\n\n    Triangle2d.relativeTo localFrame exampleTriangle\n    --> Triangle2d\n    -->     ( Point2d ( 0, -1 )\n    -->     , Point2d ( 1, -1 )\n    -->     , Point2d ( 0, 1 )\n    -->     )\n",
                "type": "Frame2d -> Triangle2d -> Triangle2d"
            },
            {
                "name": "rotateAround",
                "comment": " Rotate a triangle around a given point by a given angle (in radians).\n\n    Triangle2d.rotateAround Point2d.origin (degrees 90) exampleTriangle\n    --> Triangle2d\n    -->     ( Point2d ( -1, 1 )\n    -->     , Point2d ( -1, 2 )\n    -->     , Point2d ( -3, 1 )\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\n    -->     ( Point2d ( 2, 2 )\n    -->     , Point2d ( 4, 2 )\n    -->     , Point2d ( 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",
                "type": "Point2d -> Float -> Triangle2d -> Triangle2d"
            },
            {
                "name": "translateBy",
                "comment": " Translate a triangle by a given displacement.\n\n    displacement =\n        Vector2d ( 2, -3 )\n\n    Triangle2d.translateBy displacement exampleTriangle\n    --> Triangle2d\n    -->     ( Point2d ( 3, -2 )\n    -->     , Point2d ( 4, -2 )\n    -->     , Point2d ( 3, 0 )\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    --> p1 = Point2d ( 1, 1 )\n    --> p2 = Point2d ( 2, 1 )\n    --> p3 = Point2d ( 1, 3 )\n",
                "type": "Triangle2d -> ( Point2d, Point2d, Point2d )"
            }
        ],
        "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\nLine segments can be constructed by passing a tuple of start and end points to\nthe `LineSegment2d` constructor, for example\n\n    exampleLineSegment =\n        LineSegment2d\n            ( Point2d ( 1, 2 )\n            , Point2d ( 3, 4 )\n            )\n\n# Constructors\n\n@docs along\n\n# Endpoints\n\n@docs startPoint, endPoint, endpoints, reverse\n\n# Interpolation\n\n@docs midpoint, interpolate\n\n# Length and direction\n\n@docs length, squaredLength, direction, normalDirection, vector\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 scaleAbout, rotateAround, translateBy, mirrorAcross, projectOnto, map\n\n# Coordinate frames\n\nFunctions for transforming line segments between local and global coordinates in\ndifferent coordinate frames.\n\n@docs relativeTo, placeIn\n\n# Sketch planes\n\n@docs placeOnto\n\n# Bounds\n\n@docs boundingBox\n",
        "unions": [],
        "aliases": [],
        "values": [
            {
                "name": "along",
                "comment": " Construct a line segment collinear with the given axis, with its endpoints\nat the given distances from the axis' origin point.\n\n    LineSegment2d.along Axis2d.x 3 5\n    --> LineSegment2d ( Point2d ( 3, 0 ), Point2d ( 5, 0 ) )\n\n    LineSegment2d.along Axis2d.y 2 -4\n    --> LineSegment2d ( Point2d ( 0, 2 ), Point2d ( 0, -4 ) )\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\n    -->     { minX = 1\n    -->     , maxX = 3\n    -->     , minY = 2\n    -->     , maxY = 4\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 ( 0.7071, 0.7071 ))\n",
                "type": "LineSegment2d -> Maybe Direction2d"
            },
            {
                "name": "endPoint",
                "comment": " Get the end point of a line segment.\n\n    LineSegment2d.endPoint exampleLineSegment\n    --> Point2d ( 3, 4 )\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",
                "type": "LineSegment2d -> ( Point2d, Point2d )"
            },
            {
                "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. Negative values\nor values greater than 1 can be used to extrapolate.\n\n    LineSegment2d.interpolate exampleLineSegment 0.25\n    --> Point2d ( 1.5, 2.5 )\n\n    LineSegment2d.interpolate exampleLineSegment 1.5\n    --> Point2d ( 4, 5 )\n",
                "type": "LineSegment2d -> Float -> Point2d"
            },
            {
                "name": "length",
                "comment": " Get the length of a line segment.\n\n    LineSegment2d.length exampleLineSegment\n    --> 2.8284\n",
                "type": "LineSegment2d -> Float"
            },
            {
                "name": "map",
                "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 `map`; for example,\n\n    LineSegment2d.projectOnto Axis2d.x\n\nis equivalent to\n\n    LineSegment2d.map (Point2d.projectOnto Axis2d.x)\n",
                "type": "(Point2d -> Point2d) -> LineSegment2d -> LineSegment2d"
            },
            {
                "name": "midpoint",
                "comment": " Get the midpoint of a line segment.\n\n    LineSegment2d.midpoint exampleLineSegment\n    --> Point2d ( 2, 3 )\n",
                "type": "LineSegment2d -> Point2d"
            },
            {
                "name": "mirrorAcross",
                "comment": " Mirror a line segment across an axis.\n\n    LineSegment2d.mirrorAcross Axis2d.y exampleLineSegment\n    --> LineSegment2d\n    -->     ( Point2d ( -1, 2 )\n    -->     , Point2d ( -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",
                "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 ( -0.7071, 0.7071 ))\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.at (Point2d ( 1, 2 ))\n\n    LineSegment2d.placeIn localFrame exampleLineSegment\n    --> LineSegment2d\n    -->     ( Point2d ( 2, 4 )\n    -->     , Point2d ( 4, 6 )\n    -->     )\n",
                "type": "Frame2d -> LineSegment2d -> LineSegment2d"
            },
            {
                "name": "placeOnto",
                "comment": " Take a line segment defined in 2D coordinates within a particular sketch\nplane and return the corresponding line segment in 3D.\n\n    LineSegment2d.placeOnto SketchPlane3d.yz exampleLineSegment\n    --> LineSegment3d\n    -->     ( Point3d ( 0, 1, 2 )\n    -->     , Point3d ( 0, 3, 4 )\n    -->     )\n",
                "type": "SketchPlane3d -> LineSegment2d -> LineSegment3d"
            },
            {
                "name": "projectOnto",
                "comment": " Project a line segment onto an axis.\n\n    LineSegment2d.projectOnto Axis2d.x exampleLineSegment\n    --> LineSegment2d\n    -->     ( Point2d ( 1, 0 )\n    -->     , Point2d ( 3, 0 )\n    -->     )\n\n    LineSegment2d.projectOnto Axis2d.y exampleLineSegment\n    --> LineSegment2d\n    -->     ( Point2d ( 0, 2 )\n    -->     , Point2d ( 0, 4 )\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.at (Point2d ( 1, 2 ))\n\n    LineSegment2d.relativeTo localFrame exampleLineSegment\n    --> LineSegment2d\n    -->     ( Point2d ( 0, 0 )\n    -->     , Point2d ( 2, 2 )\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\n    -->     ( Point2d ( 3, 4 )\n    -->     , Point2d ( 1, 2 )\n    -->     )\n",
                "type": "LineSegment2d -> LineSegment2d"
            },
            {
                "name": "rotateAround",
                "comment": " Rotate around a given center point counterclockwise by a given angle (in\nradians).\n\n    LineSegment2d.rotateAround Point2d.origin (degrees 90) exampleLineSegment\n    --> LineSegment2d\n    -->     ( Point2d ( -2, 1 )\n    -->     , Point2d ( -4, 3 )\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 ( 1, 1 )\n\n    LineSegment2d.scaleAbout point 2 exampleLineSegment\n    --> LineSegment2d\n    -->     ( Point2d ( 1, 3 )\n    -->     , Point2d ( 5, 7 )\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",
                "type": "LineSegment2d -> Float"
            },
            {
                "name": "startPoint",
                "comment": " Get the start point of a line segment.\n\n    LineSegment2d.startPoint exampleLineSegment\n    --> Point2d ( 1, 2 )\n",
                "type": "LineSegment2d -> Point2d"
            },
            {
                "name": "translateBy",
                "comment": " Translate a line segment by a given displacement.\n\n    displacement =\n        Vector2d ( 1, 2 )\n\n    LineSegment2d.translateBy displacement exampleLineSegment\n    --> LineSegment2d\n    -->     ( Point2d ( 2, 4 )\n    -->     , Point2d ( 4, 6 )\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 ( 2, 2 )\n",
                "type": "LineSegment2d -> Vector2d"
            }
        ],
        "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\nThe simplest way to construct a `Point3d` value is by passing a tuple of X, Y\nand Z coordinates to the `Point3d` constructor, for example\n\n    point =\n        Point3d ( 2, 1, 3 )\n\n# Predefined points\n\n@docs origin\n\n# Constructors\n\n@docs midpoint, interpolate, along\n\n# Coordinates\n\n@docs coordinates, xCoordinate, yCoordinate, zCoordinate\n\n# Comparison\n\n@docs equalWithin\n\n# Displacement\n\n@docs vectorFrom\n\n# Distance\n\n@docs distanceFrom, squaredDistanceFrom, distanceAlong, radialDistanceFrom, squaredRadialDistanceFrom, signedDistanceFrom\n\n# Transformations\n\n@docs scaleAbout, rotateAround, translateBy, mirrorAcross, projectOnto\n\n# Coordinate frames\n\nFunctions for transforming points between local and global coordinates in\ndifferent coordinate frames.\n\n@docs relativeTo, placeIn\n\n# Sketch planes\n\n@docs projectInto\n\n# Bounds\n\n@docs hull\n",
        "unions": [],
        "aliases": [],
        "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 ( 0, 0, 2 )\n\nPositive and negative distances are interpreted relative to the direction of the\naxis:\n\n    horizontalAxis =\n        Axis3d\n            { originPoint = Point3d ( 1, 1, 1 )\n            , direction = Direction3d ( -1, 0, 0 )\n            }\n\n    Point3d.along horizontalAxis 3\n    --> Point3d ( -2, 1, 1 )\n\n    Point3d.along horizontalAxis -3\n    --> Point3d ( 4, 1, 1 )\n",
                "type": "Axis3d -> Float -> Point3d"
            },
            {
                "name": "coordinates",
                "comment": " Get the coordinates of a point as a tuple.\n\n    ( x, y, z ) =\n        Point3d.coordinates point\n",
                "type": "Point3d -> ( Float, Float, Float )"
            },
            {
                "name": "distanceAlong",
                "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\n            { originPoint = Point3d ( 1, 0, 0 )\n            , direction = Direction3d.x\n            }\n\n    point =\n        Point3d ( 3, 3, 3 )\n\n    Point3d.distanceAlong axis point\n    --> 2\n\n    Point3d.distanceAlong axis Point3d.origin\n    --> -1\n",
                "type": "Axis3d -> Point3d -> Float"
            },
            {
                "name": "distanceFrom",
                "comment": " Find the distance between two points.\n\n    p1 =\n        Point3d ( 1, 1, 2 )\n\n    p2 =\n        Point3d ( 2, 3, 4 )\n\n    Point3d.distanceFrom p1 p2\n    --> 3\n\nPartial application can be useful:\n\n    points =\n        [ Point3d ( 3, 4, 5 )\n        , Point3d ( 10, 10, 10 )\n        , Point3d ( -1, 2, -3 )\n        ]\n\n    distanceFromOrigin : Point3d -> Float\n    distanceFromOrigin =\n        Point3d.distanceFrom Point3d.origin\n\n    List.sortBy distanceFromOrigin points\n    --> [ Point3d ( -1, 2, -3 )\n    --> , Point3d ( 3, 4, 5 )\n    --> , Point3d ( 10, 10, 10 )\n    --> ]\n",
                "type": "Point3d -> 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 ( 2, 1, 3 )\n\n    secondPoint =\n        Point3d ( 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",
                "type": "Float -> Point3d -> Point3d -> Bool"
            },
            {
                "name": "hull",
                "comment": " Construct a bounding box containing both of the given points.\n\n    point1 =\n        Point3d ( 2, 1, 3 )\n\n    point2 =\n        Point3d ( -1, 5, -2 )\n\n    Point3d.hull point1 point2\n    --> BoundingBox3d\n    -->     { minX = -1\n    -->     , maxX = 2\n    -->     , minY = 1\n    -->     , maxY = 5\n    -->     , minZ = -2\n    -->     , maxZ = 3\n    -->     }\n",
                "type": "Point3d -> Point3d -> BoundingBox3d"
            },
            {
                "name": "interpolate",
                "comment": " Construct a point by interpolating between two other points based on a\nparameter that ranges from zero to one.\n\n    startPoint =\n        Point3d ( 1, 2, 4 )\n\n    endPoint =\n        Point3d ( 1, 2, 8 )\n\n    Point3d.interpolate startPoint endPoint 0.25\n    --> Point3d ( 1, 2, 5 )\n\nPartial application may be useful:\n\n    interpolatedPoint : Float -> Point3d\n    interpolatedPoint =\n        Point3d.interpolate startPoint endPoint\n\n    List.map interpolatedPoint [ 0, 0.5, 1 ]\n    --> [ Point3d ( 1, 2, 4 )\n    --> , Point3d ( 1, 2, 6 )\n    --> , Point3d ( 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 ( 1, 2, 2 )\n\n    interpolatedPoint 1.25\n    --> Point3d ( 1, 2, 9 )\n",
                "type": "Point3d -> Point3d -> Float -> Point3d"
            },
            {
                "name": "midpoint",
                "comment": " Construct a point halfway between two other points.\n\n    p1 =\n        Point3d ( 1, 1, 1 )\n\n    p2 =\n        Point3d ( 3, 7, 9 )\n\n    Point3d.midpoint p1 p2\n    --> Point3d ( 2, 4, 5 )\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 ( 1, 2, 3 )\n\n    -- Plane3d.xy is the plane Z=0\n    Point3d.mirrorAcross Plane3d.xy point\n    --> Point3d ( 1, 2, -3 )\n\n    -- Plane3d.yz is the plane X=0\n    Point3d.mirrorAcross Plane3d.yz point\n    --> Point3d ( -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 ( 0, 0, 2 )\n",
                "type": "Plane3d -> Point3d -> Point3d"
            },
            {
                "name": "origin",
                "comment": " The point (0, 0, 0).\n\n    Point3d.origin\n    --> Point3d ( 0, 0, 0 )\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.at (Point3d ( 1, 2, 3 ))\n\n    Point3d.placeIn localFrame (Point3d ( 3, 3, 3 ))\n    --> Point3d ( 4, 5, 6 )\n\n    Point3d.placeIn localFrame (Point3d ( 0, -1, -2 ))\n    --> Point3d ( 1, 1, 1 )\n",
                "type": "Frame3d -> Point3d -> Point3d"
            },
            {
                "name": "projectInto",
                "comment": " Project a point into a given sketch plane. Conceptually, this projects the\npoint onto the plane and then expresses the projected point in 2D sketch\ncoordinates.\n\n    point =\n        Point3d ( 2, 1, 3 )\n\n    Point3d.projectInto SketchPlane3d.xy point\n    --> Point2d ( 2, 1 )\n\n    Point3d.projectInto SketchPlane3d.yz point\n    --> Point2d ( 1, 3 )\n\n    Point3d.projectInto SketchPlane3d.zx point\n    --> Point2d ( 3, 2 )\n",
                "type": "SketchPlane3d -> Point3d -> Point2d"
            },
            {
                "name": "projectOnto",
                "comment": " Project a point perpendicularly onto a plane.\n\n    point =\n        Point3d ( 1, 2, 3 )\n\n    Point3d.projectOnto Plane3d.xy point\n    --> Point3d ( 1, 2, 0 )\n\n    Point3d.projectOnto Plane3d.yz point\n    --> Point3d ( 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 ( 1, 2, 1 )\n",
                "type": "Plane3d -> Point3d -> Point3d"
            },
            {
                "name": "radialDistanceFrom",
                "comment": " Find the perpendicular (nearest) distance of a point from an axis.\n\n    point =\n        Point3d ( -3, 4, 0 )\n\n    Point3d.radialDistanceFrom Axis3d.x point\n    --> 4\n\n    Point3d.radialDistanceFrom Axis3d.y point\n    --> 3\n\n    Point3d.radialDistanceFrom 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",
                "type": "Axis3d -> Point3d -> Float"
            },
            {
                "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.at (Point3d ( 1, 2, 3 ))\n\n    Point3d.relativeTo localFrame (Point3d ( 4, 5, 6 ))\n    --> Point3d ( 3, 3, 3 )\n\n    Point3d.relativeTo localFrame (Point3d ( 1, 1, 1 ))\n    --> Point3d ( 0, -1, -2 )\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 ( 3, 1, 0 )\n\n    Point3d.rotateAround axis angle point\n    --> Point3d ( 3, 0.7071, 0.7071 )\n\nRotation direction is given by the right-hand rule, counterclockwise around the\ndirection of the axis.\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 ( 1, 1, 1 )\n\n    point =\n        Point3d ( 1, 2, 3 )\n\n    Point3d.scaleAbout centerPoint 3 point\n    --> Point3d ( 1, 4, 7 )\n\n    Point3d.scaleAbout centerPoint 0.5 point\n    --> Point3d ( 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",
                "type": "Point3d -> Float -> Point3d -> Point3d"
            },
            {
                "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\n            { originPoint = Point3d ( 1, 2, 3 )\n            , normalDirection = Direction3d.y\n            }\n\n    point =\n        Point3d ( 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",
                "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 > 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",
                "type": "Point3d -> Point3d -> Float"
            },
            {
                "name": "squaredRadialDistanceFrom",
                "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`radialDistanceFrom` 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 ( 3, 4, 5 )\n\n    displacement =\n        Vector3d ( 1, 2, 3 )\n\n    Point3d.translateBy displacement point\n    --> Point3d ( 4, 6, 8 )\n",
                "type": "Vector3d -> Point3d -> Point3d"
            },
            {
                "name": "vectorFrom",
                "comment": " Find the vector from one point to another.\n\n    startPoint =\n        Point3d ( 1, 1, 1 )\n\n    endPoint =\n        Point3d ( 4, 5, 6 )\n\n    Point3d.vectorFrom startPoint endPoint\n    --> Vector3d ( 3, 4, 5 )\n",
                "type": "Point3d -> Point3d -> Vector3d"
            },
            {
                "name": "xCoordinate",
                "comment": " Get the X coordinate of a point.\n\n    Point3d.xCoordinate (Point3d ( 2, 1, 3 ))\n    --> 2\n",
                "type": "Point3d -> Float"
            },
            {
                "name": "yCoordinate",
                "comment": " Get the Y coordinate of a point.\n\n    Point3d.yCoordinate (Point3d ( 2, 1, 3 ))\n    --> 1\n",
                "type": "Point3d -> Float"
            },
            {
                "name": "zCoordinate",
                "comment": " Get the Z coordinate of a point.\n\n    Point3d.zCoordinate (Point3d ( 2, 1, 3 ))\n    --> 3\n",
                "type": "Point3d -> 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\nThe simplest way to construct a `Point2d` value is by passing a tuple of X and Y\ncoordinates to the `Point2d` constructor, for example\n\n    point =\n        Point2d ( 2, 3 )\n\nThere are no specific functions to create points from polar components, but you\ncan use Elm's built-in [`fromPolar`](http://package.elm-lang.org/packages/elm-lang/core/latest/Basics#fromPolar)\nfunction:\n\n    point =\n        Point2d (fromPolar ( radius, angle ))\n\n# Predefined points\n\n@docs origin\n\n# Constructors\n\n@docs midpoint, interpolate, along\n\n# Coordinates\n\n@docs coordinates, xCoordinate, yCoordinate\n\n# Comparison\n\n@docs equalWithin\n\n# Displacement\n\n@docs vectorFrom\n\n# Distance\n\n@docs distanceFrom, squaredDistanceFrom, distanceAlong, signedDistanceFrom\n\n# Transformations\n\n@docs scaleAbout, rotateAround, translateBy, mirrorAcross, projectOnto\n\n# Coordinate frames\n\nFunctions for transforming points between local and global coordinates in\ndifferent coordinate frames.\n\n@docs relativeTo, placeIn\n\n# Sketch planes\n\n@docs placeOnto\n\n# Bounds\n\n@docs hull\n",
        "unions": [],
        "aliases": [],
        "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 ( 0, 3 )\n\nPositive and negative distances will be interpreted relative to the direction of\nthe axis:\n\n    horizontalAxis =\n        Axis2d\n            { originPoint = Point2d ( 1, 1 )\n            , direction = Direction2d ( -1, 0 )\n            }\n\n    Point2d.along horizontalAxis 3\n    --> Point2d ( -2, 1 )\n\n    Point2d.along horizontalAxis -3\n    --> Point2d ( 4, 1 )\n",
                "type": "Axis2d -> Float -> Point2d"
            },
            {
                "name": "coordinates",
                "comment": " Get the coordinates of a point as a tuple.\n\n    ( x, y ) =\n        Point2d.coordinates point\n\nTo get the polar coordinates of a point, you can use Elm's built-in [`toPolar`](http://package.elm-lang.org/packages/elm-lang/core/latest/Basics#toPolar)\nfunction:\n\n    ( radius, angle ) =\n        toPolar (Point2d.coordinates point)\n",
                "type": "Point2d -> ( Float, Float )"
            },
            {
                "name": "distanceAlong",
                "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\n            { originPoint = Point2d ( 1, 2 )\n            , direction = Direction2d.x\n            }\n\n    point =\n        Point2d ( 3, 3 )\n\n    Point2d.distanceAlong axis point\n    --> 2\n\n    Point2d.distanceAlong axis Point2d.origin\n    --> -1\n",
                "type": "Axis2d -> Point2d -> Float"
            },
            {
                "name": "distanceFrom",
                "comment": " Find the distance between two points.\n\n    p1 =\n        Point2d ( 2, 3 )\n\n    p2 =\n        Point2d ( 5, 7 )\n\n    Point2d.distanceFrom p1 p2\n    --> 5\n\nPartial application can be useful:\n\n    points =\n        [ Point2d ( 3, 4 )\n        , Point2d ( 10, 0 )\n        , Point2d ( -1, 2 )\n        ]\n\n    distanceFromOrigin : Point2d -> Float\n    distanceFromOrigin =\n        Point2d.distanceFrom Point2d.origin\n\n    List.sortBy distanceFromOrigin points\n    --> [ Point2d ( -1, 2 )\n    --> , Point2d ( 3, 4 )\n    --> , Point2d ( 10, 0 )\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 ( 1, 2 )\n\n    secondPoint =\n        Point2d ( 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",
                "type": "Float -> Point2d -> Point2d -> Bool"
            },
            {
                "name": "hull",
                "comment": " Construct a bounding box containing both of the given points.\n\n    point1 =\n        Point2d ( 2, 3 )\n\n    point2 =\n        Point2d ( -1, 5 )\n\n    Point2d.hull point1 point2\n    --> BoundingBox2d\n    -->     { minX = -1\n    -->     , maxX = 2\n    -->     , minY = 3\n    -->     , maxY = 5\n    -->     }\n",
                "type": "Point2d -> Point2d -> BoundingBox2d"
            },
            {
                "name": "interpolate",
                "comment": " Construct a point by interpolating between two other points based on a\nparameter that ranges from zero to one.\n\n    startPoint =\n        Point2d.origin\n\n    endPoint =\n        Point2d ( 8, 12 )\n\n    Point2d.interpolate startPoint endPoint 0.25\n    --> Point2d ( 2, 3 )\n\nPartial application may be useful:\n\n    interpolatedPoint : Float -> Point2d\n    interpolatedPoint =\n        Point2d.interpolate startPoint endPoint\n\n    List.map interpolatedPoint [ 0, 0.5, 1 ]\n    --> [ Point2d ( 0, 0 )\n    --> , Point2d ( 4, 6 )\n    --> , Point2d ( 8, 12 )\n    --> ]\n\nYou can pass values less than zero or greater than one to extrapolate:\n\n    interpolatedPoint -0.5\n    --> Point2d ( -4, -6 )\n\n    interpolatedPoint 1.25\n    --> Point2d ( 10, 15 )\n",
                "type": "Point2d -> Point2d -> Float -> Point2d"
            },
            {
                "name": "midpoint",
                "comment": " Construct a point halfway between two other points.\n\n    p1 =\n        Point2d ( 1, 1 )\n\n    p2 =\n        Point2d ( 3, 7 )\n\n    Point2d.midpoint p1 p2\n    --> Point2d ( 2, 4 )\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 ( 2, 3 )\n\n    Point2d.mirrorAcross Axis2d.x point\n    --> Point2d ( 2, -3 )\n\n    Point2d.mirrorAcross Axis2d.y point\n    --> Point2d ( -2, 3 )\n",
                "type": "Axis2d -> Point2d -> Point2d"
            },
            {
                "name": "origin",
                "comment": " The point (0, 0).\n\n    Point2d.origin\n    --> Point2d ( 0, 0 )\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.at (Point2d ( 1, 2 ))\n\n    Point2d.placeIn localFrame (Point2d ( 3, 3 ))\n    --> Point2d ( 4, 5 )\n\n    Point2d.placeIn localFrame (Point2d ( 0, 1 ))\n    --> Point2d ( 1, 1 )\n",
                "type": "Frame2d -> Point2d -> Point2d"
            },
            {
                "name": "placeOnto",
                "comment": " Take a point defined in 2D coordinates within a particular sketch plane and\nreturn the corresponding point in 3D.\n\n    point =\n        Point2d ( 2, 1 )\n\n    Point2d.placeOnto SketchPlane3d.xy point\n    --> Point3d ( 2, 1, 0 )\n\n    Point2d.placeOnto SketchPlane3d.xz point\n    --> Point3d ( 2, 0, 1 )\n\nThe sketch plane can have any position and orientation:\n\n    tiltedSketchPlane =\n        SketchPlane3d.xy\n            |> SketchPlane3d.rotateAround Axis3d.x (degrees 45)\n\n    Point2d.placeOnto tiltedSketchPlane point\n    --> Point3d ( 2, 0.7071, 0.7071 )\n",
                "type": "SketchPlane3d -> Point2d -> Point3d"
            },
            {
                "name": "projectOnto",
                "comment": " Project a point perpendicularly onto an axis.\n\n    point =\n        Point2d ( 2, 3 )\n\n    Point2d.projectOnto Axis2d.x point\n    --> Point2d ( 2, 0 )\n\n    Point2d.projectOnto Axis2d.y point\n    --> Point2d ( 0, 3 )\n\nThe axis does not have to pass through the origin:\n\n    offsetYAxis =\n        Axis2d\n            { originPoint = Point2d ( 1, 0 )\n            , direction = Direction2d.y\n            }\n\n    Point2d.projectOnto offsetYAxis point\n    --> Point2d ( 1, 3 )\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.at (Point2d ( 1, 2 ))\n\n    Point2d.relativeTo localFrame (Point2d ( 4, 5 ))\n    --> Point2d ( 3, 3 )\n\n    Point2d.relativeTo localFrame (Point2d ( 1, 1 ))\n    --> Point2d ( 0, -1 )\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 ( 2, 0 )\n\n    angle =\n        degrees 45\n\n    point =\n        Point2d ( 3, 0 )\n\n    Point2d.rotateAround centerPoint angle point\n    --> Point2d ( 2.7071, 0.7071 )\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 ( 1, 1 )\n\n    point =\n        Point2d ( 2, 3 )\n\n    Point2d.scaleAbout centerPoint 3 point\n    --> Point2d ( 4, 7 )\n\n    Point2d.scaleAbout centerPoint 0.5 point\n    --> Point2d ( 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",
                "type": "Point2d -> Float -> Point2d -> Point2d"
            },
            {
                "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\n            { originPoint = Point2d ( 1, 2 )\n            , direction = Direction2d.x\n            }\n\n    point =\n        Point2d ( 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",
                "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 > 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",
                "type": "Point2d -> Point2d -> Float"
            },
            {
                "name": "translateBy",
                "comment": " Translate a point by a given displacement.\n\n    point =\n        Point2d ( 3, 4 )\n\n    displacement =\n        Vector2d ( 1, 2 )\n\n    Point2d.translateBy displacement point\n    --> Point2d ( 4, 6 )\n",
                "type": "Vector2d -> Point2d -> Point2d"
            },
            {
                "name": "vectorFrom",
                "comment": " Find the vector from one point to another.\n\n    startPoint =\n        Point2d ( 1, 1 )\n\n    endPoint =\n        Point2d ( 4, 5 )\n\n    Point2d.vectorFrom startPoint endPoint\n    --> Vector2d ( 3, 4 )\n",
                "type": "Point2d -> Point2d -> Vector2d"
            },
            {
                "name": "xCoordinate",
                "comment": " Get the X coordinate of a point.\n\n    Point2d.xCoordinate (Point2d ( 2, 3 ))\n    --> 2\n",
                "type": "Point2d -> Float"
            },
            {
                "name": "yCoordinate",
                "comment": " Get the Y coordinate of a point.\n\n    Point2d.yCoordinate (Point2d ( 2, 3 ))\n    --> 3\n",
                "type": "Point2d -> Float"
            }
        ],
        "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\nThe simplest way to construct a `Direction3d` value is by passing a tuple of X,\nY and Z components to the `Direction3d` constructor, for example\n<code>Direction3d&nbsp;(&nbsp;0,&nbsp;1,&nbsp;0&nbsp;)</code>. However, if you\ndo this **you must ensure that the sum of the squares of the given components is\nexactly one**:\n\n    Direction3d ( 1, 0, 0 )\n    Direction3d ( 0, -1, 0 )\n    Direction3d ( 0.6, 0, 0.8 )\n\nare all valid but\n\n    Direction3d ( 2, 0, 0 )\n    Direction3d ( 1, 1, 1 )\n\nare not. Instead of manually constructing `Direction3d` values, it may be easier\nto start with existing directions and transform them as necessary.\n\n# Predefined directions\n\n@docs x, y, z\n\n# Constructors\n\n@docs perpendicularTo, perpendicularBasis\n\n# Components\n\n@docs components, xComponent, yComponent, zComponent, componentIn\n\n# Comparison\n\n@docs equalWithin\n\n# Vector conversion\n\n@docs toVector\n\n# Angle measurement\n\n@docs angleFrom\n\n# Transformations\n\n@docs flip, scaleBy, rotateAround, mirrorAcross, projectOnto\n\n# Coordinate frames\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.rotateAround Axis3d.z (degrees 30) Frame3d.xyz\n\n@docs relativeTo, placeIn\n\n# Sketch planes\n\n@docs projectInto\n",
        "unions": [],
        "aliases": [],
        "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 Direction3d.y (Direction3d ( 0, -1, 0 ))\n    --> degrees 180\n",
                "type": "Direction3d -> 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 ( 0.6, 0.8, 0 )\n\n    Direction3d.componentIn Direction3d.x direction\n    --> 0.6\n\n    Direction3d.componentIn Direction3d.z direction\n    --> 0\n\n    Direction3d.componentIn direction 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",
                "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",
                "type": "Direction3d -> ( Float, Float, Float )"
            },
            {
                "name": "equalWithin",
                "comment": " Compare two directions within a tolerance. Returns true if the angle between\nthe two given directions is less than the given tolerance.\n\n    direction =\n        Direction3d.rotateAround Axis3d.z (degrees 2) Direction3d.x\n\n    Direction3d.equalWithin (degrees 5) Direction3d.x direction\n    --> True\n\n    Direction3d.equalWithin (degrees 1) Direction3d.x direction\n    --> False\n",
                "type": "Float -> Direction3d -> Direction3d -> Bool"
            },
            {
                "name": "flip",
                "comment": " Reverse a direction.\n\n    Direction3d.flip Direction3d.y\n    --> Direction3d ( 0, -1, 0 )\n",
                "type": "Direction3d -> Direction3d"
            },
            {
                "name": "mirrorAcross",
                "comment": " Mirror a direction across a plane.\n\n    direction =\n        Direction3d ( 0.6, 0, 0.8 )\n\n    Direction3d.mirrorAcross Plane3d.xy direction\n    --> Direction3d ( 0.6, 0, -0.8 )\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    offsetPlane =\n        Plane3d.offsetBy 10 Plane3d.yz\n\n    Direction3d.mirrorAcross offsetPlane direction\n    --> Direction3d ( -0.6, 0, 0.8 )\n",
                "type": "Plane3d -> 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).\n\n    Direction3d.perpendicularBasis Direction3d.x\n    --> ( Direction3d ( 0, 0, -1 )\n    --> , Direction3d ( 0, 1, 0 )\n    --> )\n\n    Direction3d.perpendicularBasis Direction3d.y\n    --> ( Direction3d ( 0, 0, 1 )\n    --> , Direction3d ( 1, 0, 0 )\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 ( 0, 0, -1 )\n\n    Direction3d.perpendicularTo Direction3d.y\n    --> Direction3d ( 0, 0, 1 )\n\n    direction =\n        Direction3d ( 0.6, 0, 0.8 )\n\n    Direction3d.perpendicularTo direction\n    --> Direction3d ( 0.8, 0, -0.6 )\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 ( 0.866, 0.5, 0 )\n\n    Direction3d.placeIn rotatedFrame Direction3d.y\n    --> Direction3d ( -0.5, 0.866, 0 )\n\n    Direction3d.placeIn rotatedFrame Direction3d.z\n    --> Direction3d ( 0, 0, 1 )\n",
                "type": "Frame3d -> Direction3d -> Direction3d"
            },
            {
                "name": "projectInto",
                "comment": " Project a direction into a given sketch plane. Conceptually, this projects\nthe direction onto the plane and then expresses the projected direction in 2D\nsketch 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 ( 0.6, -0.8, 0 )\n\n    Direction3d.projectInto SketchPlane3d.xy direction\n    --> Just (Direction2d ( 0.6, -0.8 ))\n\n    Direction3d.projectInto SketchPlane3d.xz direction\n    --> Just (Direction2d ( 1, 0 ))\n\n    Direction3d.projectInto SketchPlane3d.yz direction\n    --> Just (Direction2d ( -1, 0 ))\n\n    Direction3d.projectInto SketchPlane3d.xy Direction3d.z\n    --> Nothing\n",
                "type": "SketchPlane3d -> Direction3d -> Maybe Direction2d"
            },
            {
                "name": "projectOnto",
                "comment": " Project a direction onto a plane. This is effectively the direction of the\ngiven direction's 'shadow' on the given plane. If the given direction is\nexactly perpendicular to the given plane, then `Nothing` is returned.\n\n    direction =\n        Direction3d ( 0.6, -0.8, 0 )\n\n    Direction3d.projectOnto Plane3d.xy direction\n    --> Just (Direction3d ( 0.6, -0.8, 0 ))\n\n    Direction3d.projectOnto Plane3d.xz direction\n    --> Just (Direction3d ( 1, 0, 0 ))\n\n    Direction3d.projectOnto Plane3d.yz direction\n    --> Just (Direction3d ( 0, -1, 0 ))\n\n    Direction3d.projectOnto Plane3d.xy Direction3d.z\n    --> Nothing\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 ( 0.866, -0.5, 0 )\n\n    Direction3d.relativeTo rotatedFrame Direction3d.y\n    --> Direction3d ( 0.5, 0.866, 0 )\n\n    Direction3d.relativeTo rotatedFrame Direction3d.z\n    --> Direction3d ( 0, 0, 1 )\n",
                "type": "Frame3d -> Direction3d -> Direction3d"
            },
            {
                "name": "rotateAround",
                "comment": " Rotate a direction around an axis by a given angle.\n\n    Direction3d.rotateAround Axis3d.x (degrees 90) Direction3d.y\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 = Point3d ( 100, 200, 300 )\n            , direction = Direction3d.z\n            }\n\n    Direction3d.rotateAround offsetAxis (degrees 90) Direction3d.x\n    --> Direction3d.y\n\n",
                "type": "Axis3d -> Float -> Direction3d -> Direction3d"
            },
            {
                "name": "scaleBy",
                "comment": " Construct a vector of a particular length by treating a direction as a unit\nvector and scaling it by the given length.\n\n    Direction3d.scaleBy 3 Direction3d.z\n    --> Vector3d ( 0, 0, 3 )\n\nThe length can be negative, in which case the resulting vector will have the\nopposite direction.\n",
                "type": "Float -> Direction3d -> Vector3d"
            },
            {
                "name": "toVector",
                "comment": " Convert a direction to a unit vector.\n\n    Direction3d.toVector Direction3d.y\n    --> Vector3d ( 0, 1, 0 )\n",
                "type": "Direction3d -> Vector3d"
            },
            {
                "name": "x",
                "comment": " The positive X direction.\n\n    Direction3d.x\n    --> Direction3d ( 1, 0, 0 )\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",
                "type": "Direction3d -> Float"
            },
            {
                "name": "y",
                "comment": " The positive Y direction.\n\n    Direction3d.y\n    --> Direction3d ( 0, 1, 0 )\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",
                "type": "Direction3d -> Float"
            },
            {
                "name": "z",
                "comment": " The positive Z direction.\n\n    Direction3d.z\n    --> Direction3d ( 0, 0, 1 )\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",
                "type": "Direction3d -> Float"
            }
        ],
        "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\nThe simplest way to construct a `Direction2d` value is by passing a tuple of X\nand Y components to the `Direction2d` constructor, for example\n<code>Direction2d&nbsp;(&nbsp;1,&nbsp;0&nbsp;)</code>. However, if you do this\n**you must ensure that the sum of the squares of the given components is exactly\none**:\n\n    Direction2d ( 1, 0 )\n    Direction2d ( 0, -1 )\n    Direction2d ( 0.6, 0.8 )\n\nare all valid but\n\n    Direction2d ( 2, 0 )\n    Direction2d ( 1, 1 )\n\nare not. Instead of manually constructing `Direction2d` values, it may be easier\nto use constructors like `Direction2d.fromAngle` or start with existing\ndirections and transform them as necessary.\n\n# Predefined directions\n\n@docs x, y\n\n# Constructors\n\n@docs perpendicularTo\n\n# Angles\n\n@docs fromAngle, toAngle, angleFrom\n\n# Components\n\n@docs components, xComponent, yComponent, componentIn\n\n# Comparison\n\n@docs equalWithin\n\n# Vector conversion\n\n@docs toVector\n\n# Transformations\n\n@docs flip, scaleBy, rotateBy, mirrorAcross\n\n# Coordinate frames\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.x\n            , yDirection = Direction2d.flip Direction2d.y\n            }\n\n    rotatedFrame =\n        Frame2d.rotateBy (degrees 30) Frame2d.xy\n\n@docs relativeTo, placeIn\n\n# Sketch planes\n\n@docs placeOnto\n",
        "unions": [],
        "aliases": [],
        "values": [
            {
                "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",
                "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 Direction2d.x Direction2d.x\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",
                "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",
                "type": "Direction2d -> ( Float, Float )"
            },
            {
                "name": "equalWithin",
                "comment": " Compare two directions within a tolerance. Returns true if the angle between\nthe two given directions is less than the given tolerance.\n\n    firstDirection =\n        Direction2d.fromAngle (degrees 45)\n\n    secondDirection =\n        Direction2d.fromAngle (degrees 47)\n\n    Direction2d.equalWithin (degrees 5) firstDirection secondDirection\n    --> True\n\n    Direction2d.equalWithin (degrees 1) firstDirection secondDirection\n    --> False\n",
                "type": "Float -> Direction2d -> Direction2d -> Bool"
            },
            {
                "name": "flip",
                "comment": " Reverse a direction.\n\n    Direction2d.flip Direction2d.y\n    --> Direction2d ( 0, -1 )\n",
                "type": "Direction2d -> 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 135)\n    --> Direction2d ( -0.7071, 0.7071 )\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\n            { originPoint = Point2d ( 100, 200 )\n            , direction = 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",
                "type": "Axis2d -> Direction2d -> Direction2d"
            },
            {
                "name": "perpendicularTo",
                "comment": " Construct a direction perpendicular to the given direction, by rotating the\ngiven direction 90 degrees counterclockwise.\n\n    Direction2d.perpendicularTo Direction2d.x\n    --> Direction2d.y\n\n    Direction2d.perpendicularTo Direction2d.y\n    --> Direction2d ( -1, 0 )\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 ( 0, -1 )\n\n    Direction2d.placeIn rotatedFrame Direction2d.x\n    --> Direction2d ( 0.866, 0.5 )\n\n    Direction2d.placeIn rotatedFrame Direction2d.y\n    --> Direction2d ( -0.5, 0.866 )\n",
                "type": "Frame2d -> Direction2d -> Direction2d"
            },
            {
                "name": "placeOnto",
                "comment": " Take a direction defined in 2D coordinates within a particular sketch plane\nand return the corresponding direction in 3D.\n\n    direction =\n        Direction2d ( 0.6, 0.8 )\n\n    Direction2d.placeOnto SketchPlane3d.xy direction\n    --> Direction3d ( 0.6, 0.8, 0 )\n\n    Direction2d.placeOnto SketchPlane3d.yz direction\n    --> Direction3d ( 0, 0.6, 0.8 )\n\n    Direction2d.placeOnto SketchPlane3d.zx direction\n    --> Direction3d ( 0.8, 0, 0.6 )\n",
                "type": "SketchPlane3d -> Direction2d -> 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    Direction2d.relativeTo upsideDownFrame Direction2d.y\n    --> Direction2d ( 0, -1 )\n\n    Direction2d.relativeTo rotatedFrame Direction2d.x\n    --> Direction2d ( 0.866, -0.5 )\n\n    Direction2d.relativeTo rotatedFrame Direction2d.y\n    --> Direction2d ( 0.5, 0.866 )\n",
                "type": "Frame2d -> Direction2d -> Direction2d"
            },
            {
                "name": "rotateBy",
                "comment": " Rotate a direction counterclockwise by a given angle (in radians).\n\n    Direction2d.rotateBy (degrees 45) Direction2d.x\n    --> Direction2d ( 0.7071, 0.7071 )\n\n    Direction2d.rotateBy pi Direction2d.y\n    --> Direction2d.flip Direction2d.y\n",
                "type": "Float -> Direction2d -> Direction2d"
            },
            {
                "name": "scaleBy",
                "comment": " Construct a vector of a particular length by treating a direction as a unit\nvector and scaling it by the given length.\n\n    direction =\n        Direction2d ( 0.6, 0.8 )\n\n    Direction2d.scaleBy 2 direction\n    --> Vector2d ( 1.2, 1.6 )\n\nThe length can be negative, in which case the resulting vector will have the\nopposite direction.\n",
                "type": "Float -> Direction2d -> Vector2d"
            },
            {
                "name": "toAngle",
                "comment": " Convert a direction to a counterclockwise angle in radians from the positive\nX direction. The result will be in the range -π to π.\n\n    Direction2d.toAngle Direction2d.x\n    --> 0\n\n    Direction2d.toAngle Direction2d.y\n    --> degrees 90\n\n    Direction2d.toAngle (Direction2d ( 0, -1 ))\n    --> degrees -90\n",
                "type": "Direction2d -> Float"
            },
            {
                "name": "toVector",
                "comment": " Convert a direction to a unit vector.\n\n    Direction2d.toVector Direction2d.x\n    --> Vector2d ( 1, 0 )\n",
                "type": "Direction2d -> Vector2d"
            },
            {
                "name": "x",
                "comment": " The positive X direction.\n\n    Direction2d.x\n    --> Direction2d ( 1, 0 )\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",
                "type": "Direction2d -> Float"
            },
            {
                "name": "y",
                "comment": " The positive Y direction.\n\n    Direction2d.y\n    --> Direction2d ( 0, 1 )\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",
                "type": "Direction2d -> Float"
            }
        ],
        "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 boundingBox2d, boundingBox3d\n@docs polyline2d, polyline3d, polygon2d\n@docs circle2d\n",
        "unions": [],
        "aliases": [],
        "values": [
            {
                "name": "axis2d",
                "comment": " Decodes an Axis2d from an object with `originPoint` and `direction` fields.\n",
                "type": "Decoder Axis2d"
            },
            {
                "name": "axis3d",
                "comment": " Decodes an Axis3d from an object with `originPoint` and `direction` fields.\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`, `maxY`,\n`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": "direction2d",
                "comment": " Decodes a Direction2d from a list of two floating-point components.\n",
                "type": "Decoder Direction2d"
            },
            {
                "name": "direction3d",
                "comment": " Decodes a Direction3d from a list of three floating-point components.\n",
                "type": "Decoder Direction3d"
            },
            {
                "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": "lineSegment2d",
                "comment": " Decodes a LineSegment2d from a list of two endpoints.\n",
                "type": "Decoder LineSegment2d"
            },
            {
                "name": "lineSegment3d",
                "comment": " Decodes a LineSegment3d from a list 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 a list of two floating-point coordinates.\n",
                "type": "Decoder Point2d"
            },
            {
                "name": "point3d",
                "comment": " Decodes a Point3d from a list of three floating-point coordinates.\n",
                "type": "Decoder Point3d"
            },
            {
                "name": "polygon2d",
                "comment": " Decodes a Polygon2d from a list of vertices.\n",
                "type": "Decoder Polygon2d"
            },
            {
                "name": "polyline2d",
                "comment": " Decodes a Polyline2d from a list of vertices.\n",
                "type": "Decoder Polyline2d"
            },
            {
                "name": "polyline3d",
                "comment": " Decodes a Polyline3d from a list of vertices.\n",
                "type": "Decoder Polyline3d"
            },
            {
                "name": "sketchPlane3d",
                "comment": " Decodes a SketchPlane3d from an object with `originPoint`, `xDirection` and\n`yDirection` fields.\n",
                "type": "Decoder SketchPlane3d"
            },
            {
                "name": "triangle2d",
                "comment": " Decodes a Triangle2d from a list of three vertices.\n",
                "type": "Decoder Triangle2d"
            },
            {
                "name": "triangle3d",
                "comment": " Decodes a Triangle3d from a list of three vertices.\n",
                "type": "Decoder Triangle3d"
            },
            {
                "name": "vector2d",
                "comment": " Decodes a Vector2d from a list of two floating-point components.\n",
                "type": "Decoder Vector2d"
            },
            {
                "name": "vector3d",
                "comment": " Decodes a Vector3d from a list of three floating-point components.\n",
                "type": "Decoder Vector3d"
            }
        ],
        "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\nThe simplest way to create a `Vector3d` is by passing a tuple of X, Y and Z\ncomponents to the `Vector3d` constructor, for example\n\n    vector =\n        Vector3d ( 2, 1, 3 )\n\n# Predefined vectors\n\n@docs zero\n\nAlthough there are no predefined constants for\n<code>Vector3d&nbsp;(&nbsp;1,&nbsp;0,&nbsp;0&nbsp;)</code>,\n<code>Vector3d&nbsp;(&nbsp;0,&nbsp;1,&nbsp;0&nbsp;)</code> and\n<code>Vector3d&nbsp;(&nbsp;0,&nbsp;0,&nbsp;1&nbsp;)</code>, in most cases you\nwill actually want their `Direction3d` versions [`Direction3d.x`](OpenSolid-Direction3d#x),\n[`Direction3d.y`](OpenSolid-Direction3d#y) and [`Direction3d.z`](OpenSolid-Direction3d#z).\n\n# Constructors\n\n@docs perpendicularTo\n\n# Components\n\n@docs components, xComponent, yComponent, zComponent, componentIn\n\n# Comparison\n\n@docs equalWithin\n\n# Length and direction\n\n@docs length, squaredLength, direction, lengthAndDirection\n\n# Arithmetic\n\n@docs sum, difference, dotProduct, crossProduct\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, scaleBy, rotateAround, mirrorAcross, projectionIn, projectOnto\n\n# Coordinate frames\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, 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\n\n# Sketch planes\n\nFunctions for converting vectors between global 3D coordinates and 2D\ncoordinates within a particular sketch plane.\n\n@docs projectInto\n",
        "unions": [],
        "aliases": [],
        "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",
                "type": "Direction3d -> Vector3d -> Float"
            },
            {
                "name": "components",
                "comment": " Extract the components of a vector.\n\n    Vector3d.components (Vector2d ( 2, 3, 4 ))\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",
                "type": "Vector3d -> ( Float, Float, Float )"
            },
            {
                "name": "crossProduct",
                "comment": " Find the cross product of two vectors.\n\n    firstVector =\n        Vector3d ( 2, 0, 0 )\n\n    secondVector =\n        Vector3d ( 0, 3, 0 )\n\n    Vector3d.crossProduct firstVector secondVector\n    --> Vector3d ( 0, 0, 6 )\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 ( 5, 6, 7 )\n\n    secondVector =\n        Vector3d ( 1, 1, 1 )\n\n    Vector3d.difference firstVector secondVector\n    --> Vector3d ( 4, 5, 6 )\n",
                "type": "Vector3d -> Vector3d -> Vector3d"
            },
            {
                "name": "direction",
                "comment": " Attempt to find the direction of a vector. In the case of a zero vector,\nreturn `Nothing`.\n\n    Vector3d.direction (Vector3d ( 3, 0, 4 ))\n    --> Just (Direction3d ( 0.6, 0, 0.8 ))\n\n    Vector3d.direction (Vector3d ( 0, 0, 0 ))\n    --> Nothing\n",
                "type": "Vector3d -> Maybe Direction3d"
            },
            {
                "name": "dotProduct",
                "comment": " Find the dot product of two vectors.\n\n    firstVector =\n        Vector3d ( 1, 0, 2 )\n\n    secondVector =\n        Vector3d ( 3, 4, 5 )\n\n    Vector3d.dotProduct firstVector secondVector\n    --> 13\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 ( 2, 1, 3 )\n\n    secondVector =\n        Vector3d ( 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",
                "type": "Float -> Vector3d -> Vector3d -> Bool"
            },
            {
                "name": "flip",
                "comment": " Reverse the direction of a vector, negating its components.\n\n    Vector3d.flip (Vector3d ( 1, -3, 2 ))\n    --> Vector3d ( -1, 3, -2 )\n",
                "type": "Vector3d -> Vector3d"
            },
            {
                "name": "length",
                "comment": " Get the length (magnitude) of a vector.\n\n    Vector3d.length (Vector3d ( 2, 1, 2 ))\n    --> 3\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 ( 3, 0, 4 )\n\n    Vector3d.lengthAndDirection vector\n    --> Just ( 5, Direction3d ( 0.6, 0, 0.8 ) )\n\n    Vector3d.lengthAndDirection Vector3d.zero\n    --> Nothing\n",
                "type": "Vector3d -> Maybe ( Float, Direction3d )"
            },
            {
                "name": "mirrorAcross",
                "comment": " Mirror a vector across a plane.\n\n    vector =\n        Vector3d ( 1, 2, 3 )\n\n    Vector3d.mirrorAcross Plane3d.xy vector\n    --> Vector3d ( 1, 2, -3 )\n\n    Vector3d.mirrorAcross Plane3d.yz vector\n    --> Vector3d ( -1, 2, 3 )\n",
                "type": "Plane3d -> Vector3d -> Vector3d"
            },
            {
                "name": "perpendicularTo",
                "comment": " Construct an arbitrary vector perpendicular to the given vector. The exact\nmagnitude 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 (Vector3d ( 3, 0, 0 ))\n    --> Vector3d ( 0, 0, -3 )\n\n    Vector3d.perpendicularTo (Vector3d ( 1, 2, 3 ))\n    --> Vector3d ( 0, -3, 2 )\n\n    Vector3d.perpendicularTo Vector3d.zero\n    --> Vector3d.zero\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 ( 2, 0, 3 )\n\n    Vector3d.placeIn rotatedFrame vector\n    --> Vector3d ( 1.732, 1, 3 )\n",
                "type": "Frame3d -> Vector3d -> Vector3d"
            },
            {
                "name": "projectInto",
                "comment": " Project a vector into a given sketch plane. Conceptually, this projects the\nvector onto the plane and then expresses the projected vector in 2D sketch\ncoordinates.\n\n    vector =\n        Vector3d ( 2, 1, 3 )\n\n    Vector3d.projectInto SketchPlane3d.xy vector\n    --> Vector2d ( 2, 1 )\n\n    Vector3d.projectInto SketchPlane3d.yz vector\n    --> Vector2d ( 1, 3 )\n\n    Vector3d.projectInto SketchPlane3d.zx vector\n    --> Vector2d ( 3, 2 )\n",
                "type": "SketchPlane3d -> Vector3d -> Vector2d"
            },
            {
                "name": "projectOnto",
                "comment": " Project a vector onto a plane. Conceptually, this means splitting the\noriginal vector into a portion parallel to the plane (perpendicular to the\nplane's normal direction) and a portion perpendicular to it (parallel to its\nnormal direction), then returning the parallel (in-plane) portion.\n\n    vector =\n        Vector3d ( 2, 1, 3 )\n\n    Vector3d.projectOnto Plane3d.xy vector\n    --> Vector3d ( 2, 1, 0 )\n\n    Vector3d.projectOnto Plane3d.xz vector\n    --> Vector3d ( 2, 0, 3 )\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 ( 1, 2, 3 )\n\n    Vector3d.projectionIn Direction3d.x vector\n    --> Vector3d ( 1, 0, 0 )\n\n    Vector3d.projectionIn Direction3d.z vector\n    --> Vector3d ( 0, 0, 3 )\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 ( 2, 0, 3 )\n\n    Vector3d.relativeTo rotatedFrame vector\n    --> Vector3d ( 1.732, -1, 3 )\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 ( 2, 0, 1 )\n\n    Vector3d.rotateAround Axis3d.x (degrees 90) vector\n    --> Vector3d ( 2, -1, 0 )\n\n    Vector3d.rotateAround Axis3d.z (degrees 45) vector\n    --> Vector3d ( 1.4142, 1.4142, 1 )\n",
                "type": "Axis3d -> Float -> Vector3d -> Vector3d"
            },
            {
                "name": "scaleBy",
                "comment": " Scale the length of a vector by a given scale.\n\n    Vector3d.scaleBy 3 (Vector3d ( 1, 2, 3 ))\n    --> Vector3d ( 3, 6, 9 )\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",
                "type": "Vector3d -> Float"
            },
            {
                "name": "sum",
                "comment": " Find the sum of two vectors.\n\n    firstVector =\n        Vector3d ( 1, 2, 3 )\n\n    secondVector =\n        Vector3d ( 4, 5, 6 )\n\n    Vector3d.sum firstVector secondVector\n    --> Vector3d ( 5, 7, 9 )\n",
                "type": "Vector3d -> Vector3d -> Vector3d"
            },
            {
                "name": "xComponent",
                "comment": " Get the X component of a vector.\n\n    Vector3d.xComponent (Vector3d ( 1, 2, 3 ))\n    --> 1\n",
                "type": "Vector3d -> Float"
            },
            {
                "name": "yComponent",
                "comment": " Get the Y component of a vector.\n\n    Vector3d.yComponent (Vector3d ( 1, 2, 3 ))\n    --> 2\n",
                "type": "Vector3d -> Float"
            },
            {
                "name": "zComponent",
                "comment": " Get the Z component of a vector.\n\n    Vector3d.zComponent (Vector3d ( 1, 2, 3 ))\n    --> 3\n",
                "type": "Vector3d -> Float"
            },
            {
                "name": "zero",
                "comment": " The zero vector.\n\n    Vector3d.zero\n    --> Vector3d ( 0, 0, 0 )\n",
                "type": "Vector3d"
            }
        ],
        "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\nThe simplest way to create a `Vector2d` is  by passing a tuple of X and Y\ncomponents to the `Vector2d` constructor, for example\n\n    vector =\n        Vector2d ( 2, 3 )\n\nThere are no specific functions to create vectors from polar components, but you\ncan use Elm's built-in [`fromPolar`](http://package.elm-lang.org/packages/elm-lang/core/latest/Basics#fromPolar)\nfunction:\n\n    vector =\n        Vector2d (fromPolar ( radius, angle ))\n\n# Predefined vectors\n\n@docs zero\n\nAlthough there are no predefined constants for\n<code>Vector2d&nbsp;(&nbsp;1,&nbsp;0&nbsp;)</code> and\n<code>Vector2d&nbsp;(&nbsp;0,&nbsp;1&nbsp;)</code>, in most cases you will\nactually want their `Direction2d` versions [`Direction2d.x`](OpenSolid-Direction2d#x)\nand [`Direction2d.y`](OpenSolid-Direction2d#y).\n\n# Constructors\n\n@docs perpendicularTo\n\n# Components\n\n@docs components, xComponent, yComponent, componentIn\n\n# Comparison\n\n@docs equalWithin\n\n# Length and direction\n\n@docs length, squaredLength, direction, lengthAndDirection\n\n# Arithmetic\n\n@docs sum, difference, dotProduct, crossProduct\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, scaleBy, rotateBy, mirrorAcross, projectionIn, projectOnto\n\n# Coordinate frames\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# Sketch planes\n\n@docs placeOnto\n",
        "unions": [],
        "aliases": [],
        "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",
                "type": "Direction2d -> Vector2d -> Float"
            },
            {
                "name": "components",
                "comment": " Extract the components of a vector.\n\n    Vector2d.components (Vector2d ( 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\nTo get the polar components of a vector, you can use Elm's built-in [`toPolar`](http://package.elm-lang.org/packages/elm-lang/core/latest/Basics#toPolar)\nfunction:\n\n    ( radius, angle ) =\n        toPolar (Vector2d.components vector)\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 magnitude is equal to the product of the lengths of the two given\n    vectors and the sine of the angle between them, so it can be used as a\n    metric to 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 ( 2, 0 )\n\n    secondVector =\n        Vector2d ( 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",
                "type": "Vector2d -> Vector2d -> Float"
            },
            {
                "name": "difference",
                "comment": " Find the difference between two vectors (the first vector minus the second).\n\n    firstVector =\n        Vector2d ( 5, 6 )\n\n    secondVector =\n        Vector2d ( 1, 3 )\n\n    Vector2d.difference firstVector secondVector\n    --> Vector2d ( 4, 3 )\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 ( 3, 4 ))\n    --> Just (Direction2d ( 0.6, 0.8 ))\n\n    Vector2d.direction (Vector2d ( 0, 0 ))\n    --> Nothing\n",
                "type": "Vector2d -> Maybe Direction2d"
            },
            {
                "name": "dotProduct",
                "comment": " Find the dot product of two vectors.\n\n    firstVector =\n        Vector2d ( 1, 2 )\n\n    secondVector =\n        Vector2d ( 3, 4 )\n\n    Vector2d.dotProduct firstVector secondVector\n    --> 11\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 ( 1, 2 )\n\n    secondVector =\n        Vector2d ( 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",
                "type": "Float -> Vector2d -> Vector2d -> Bool"
            },
            {
                "name": "flip",
                "comment": " Reverse the direction of a vector, negating its components.\n\n    Vector2d.flip (Vector2d ( -1, 2 ))\n    --> Vector2d ( 1, -2 )\n",
                "type": "Vector2d -> Vector2d"
            },
            {
                "name": "length",
                "comment": " Get the length (magnitude) of a vector.\n\n    Vector2d.length (Vector2d ( 3, 4 ))\n    --> 5\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 ( 3, 4 )\n\n    Vector2d.lengthAndDirection vector\n    --> Just ( 5, Direction2d ( 0.6, 0.8 ) )\n\n    Vector2d.lengthAndDirection Vector2d.zero\n    --> Nothing\n",
                "type": "Vector2d -> Maybe ( Float, Direction2d )"
            },
            {
                "name": "mirrorAcross",
                "comment": " Mirror a vector across a given axis.\n\n    vector =\n        Vector2d ( 2, 3 )\n\n    Vector2d.mirrorAcross Axis2d.y vector\n    --> Vector2d ( -2, 3 )\n\n    horizontalAxis =\n        Axis2d\n            { originPoint = Point2d ( 100, 200 )\n            , direction = Direction2d.x\n            }\n\n    Vector2d.mirrorAcross horizontalAxis vector\n    --> Vector2d ( 2, -3 )\n",
                "type": "Axis2d -> 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 (Vector2d ( 1, 0 ))\n    --> Vector2d ( 0, 1 )\n\n    Vector2d.perpendicularTo (Vector2d ( 0, 2 ))\n    --> Vector2d ( -2, 0 )\n\n    Vector2d.perpendicularTo (Vector2d ( 3, 1 ))\n    --> Vector2d ( -1, 3 )\n\n    Vector2d.perpendicularTo Vector2d.zero\n    --> Vector2d.zero\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.placeIn rotatedFrame (Vector2d ( 2, 0 ))\n    --> Vector2d ( 1.732, 1 )\n",
                "type": "Frame2d -> Vector2d -> Vector2d"
            },
            {
                "name": "placeOnto",
                "comment": " Take a vector defined in 2D coordinates within a particular sketch plane and\nreturn the corresponding vector in 3D.\n\n    vector =\n        Vector2d ( 2, 3 )\n\n    Vector2d.placeOnto SketchPlane3d.xy vector\n    --> Vector3d ( 2, 3, 0 )\n\n    Vector2d.placeOnto SketchPlane3d.yz vector\n    --> Vector3d ( 0, 2, 3 )\n\n    Vector2d.placeOnto SketchPlane3d.zx vector\n    --> Vector3d ( 3, 0, 2 )\n\nA slightly more complex example:\n\n    tiltedSketchPlane =\n        SketchPlane3d.xy\n            |> SketchPlane3d.rotateAround Axis3d.x (degrees 45)\n\n    Vector2d.placeOnto tiltedSketchPlane (Vector2d ( 1, 1 ))\n    --> Vector3d ( 1, 0.7071, 0.7071 )\n",
                "type": "SketchPlane3d -> Vector2d -> Vector3d"
            },
            {
                "name": "projectOnto",
                "comment": " Project a vector onto an axis.\n\n    Vector2d.projectOnto Axis2d.y (Vector2d ( 3, 4 ))\n    --> Vector2d ( 0, 4 )\n\n    Vector2d.projectOnto Axis2d.x (Vector2d ( -1, 2 ))\n    --> Vector2d ( -1, 0 )\n\nThis is equivalent to finding the projection in the axis' direction.\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 ( 2, 3 )\n\n    Vector2d.projectionIn Direction2d.x vector\n    --> Vector2d ( 2, 0 )\n\n    Vector2d.projectionIn Direction2d.y vector\n    --> Vector2d ( 0, 3 )\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.relativeTo rotatedFrame (Vector2d ( 2, 0 ))\n    --> Vector2d ( 1.732, -1 )\n",
                "type": "Frame2d -> Vector2d -> Vector2d"
            },
            {
                "name": "rotateBy",
                "comment": " Rotate a vector counterclockwise by a given angle (in radians).\n\n    Vector2d.rotateBy (degrees 45) (Vector2d ( 1, 1 ))\n    --> Vector2d ( 0, 1.4142 )\n\n    Vector2d.rotateBy pi (Vector2d ( 1, 0 ))\n    --> Vector2d ( -1, 0 )\n",
                "type": "Float -> Vector2d -> Vector2d"
            },
            {
                "name": "scaleBy",
                "comment": " Scale the length of a vector by a given scale.\n\n    Vector2d.scaleBy 3 (Vector2d ( 1, 2 ))\n    --> Vector2d ( 3, 6 )\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",
                "type": "Vector2d -> Float"
            },
            {
                "name": "sum",
                "comment": " Find the sum of two vectors.\n\n    firstVector =\n        Vector2d ( 1, 2 )\n\n    secondVector =\n        Vector2d ( 3, 4 )\n\n    Vector2d.sum firstVector secondVector\n    --> Vector2d ( 4, 6 )\n",
                "type": "Vector2d -> Vector2d -> Vector2d"
            },
            {
                "name": "xComponent",
                "comment": " Get the X component of a vector.\n\n    Vector2d.xComponent (Vector2d ( 2, 3 ))\n    --> 2\n",
                "type": "Vector2d -> Float"
            },
            {
                "name": "yComponent",
                "comment": " Get the Y component of a vector.\n\n    Vector2d.yComponent (Vector2d ( 2, 3 ))\n    --> 3\n",
                "type": "Vector2d -> Float"
            },
            {
                "name": "zero",
                "comment": " The zero vector.\n\n    Vector2d.zero\n    --> Vector2d ( 0, 0 )\n",
                "type": "Vector2d"
            }
        ],
        "binops": []
    },
    {
        "name": "OpenSolid.Scalar",
        "comment": " Convenience functions for working with scalar (floating-point) values.\n\n@docs equalWithin\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",
                "type": "Float -> Float -> Float -> Bool"
            }
        ],
        "binops": []
    },
    {
        "name": "OpenSolid.Geometry.Types",
        "comment": " This module contains the definitions of the core OpenSolid data types. Each\ntype also has a corresponding module providing related functionality. Suggested\npractice is to import this module exposing everything, and import all other\nnecessary modules using `as`, for example:\n\n    import OpenSolid.Geometry.Types exposing (..)\n    import OpenSolid.Vector2d as Vector2d\n    import OpenSolid.Plane3d as Plane3d\n\n# Vectors\n\nVectors represent quantities such as displacements or velocities. For positions,\n`Point2d` or `Point3d` should be used instead.\n\n@docs Vector2d, Vector3d\n\n# Directions\n\nA direction is effectively a vector with a length of one, used to represent\nquantities like the direction of an axis or the normal direction of a plane.\n\n@docs Direction2d, Direction3d\n\n# Points\n\nPoints represent positions in space. They are distinct from vectors but interact\nwith them in well-defined ways; you can translate a point by a vector to result\nin a new point, or you can compute the vector from one point to another, but you\ncannot 'add' two points like you can add two vectors.\n\n@docs Point2d, Point3d\n\n# Datums\n\nAxes and planes are used extensively within OpenSolid to define different types\nof transformations. For instance, rotation in 3D is defined by a rotation axis\nand mirroring in 3D is defined by a mirror plane.\n\n@docs Axis2d, Axis3d, Plane3d\n\n# Frames\n\nFrames represent local coordinate systems, and allow for conversions between\nlocal and global coordinates. They are also a common source of datums used in\ntransformations, for example rotating around the Z axis of a 3D frame or\nmirroring across its XY plane.\n\n@docs Frame2d, Frame3d\n\n# Sketch planes\n\n@docs SketchPlane3d\n\n# Line segments\n\n@docs LineSegment2d, LineSegment3d\n\n# Triangles\n\n@docs Triangle2d, Triangle3d\n\n# Bounding boxes\n\nThese types represent bounding boxes around other geometric objects, and are\nuseful for tasks such as fast spatial searching or culling non-visible objects\nduring 3D rendering.\n\n@docs BoundingBox2d, BoundingBox3d\n\n# Polylines\n\n@docs Polyline2d, Polyline3d\n\n# Polygons\n\n@docs Polygon2d\n\n# Circles\n\n@docs Circle2d\n",
        "unions": [
            {
                "name": "Axis2d",
                "comment": " ![Axis2d](https://opensolid.github.io/images/geometry/icons/axis2d.svg)\n\nAn axis in 2D, defined by its origin point and direction. See the [`Axis2d`](OpenSolid-Axis2d)\nmodule for details.\n",
                "args": [],
                "cases": [
                    [
                        "Axis2d",
                        [
                            "{ originPoint : Point2d, direction : Direction2d }"
                        ]
                    ]
                ]
            },
            {
                "name": "Axis3d",
                "comment": " ![Axis3d](https://opensolid.github.io/images/geometry/icons/axis3d.svg)\n\nAn axis in 3D, defined by its origin point and direction. See the [`Axis3d`](OpenSolid-Axis3d)\nmodule for details.\n",
                "args": [],
                "cases": [
                    [
                        "Axis3d",
                        [
                            "{ originPoint : Point3d, direction : Direction3d }"
                        ]
                    ]
                ]
            },
            {
                "name": "BoundingBox2d",
                "comment": " ![BoundingBox2d](https://opensolid.github.io/images/geometry/icons/boundingBox2d.svg)\n\nA bounding box in 2D, defined by its minimum and maximum X and Y values. See the\n[`BoundingBox2d`](OpenSolid-BoundingBox2d) module for details.\n",
                "args": [],
                "cases": [
                    [
                        "BoundingBox2d",
                        [
                            "{ minX : Float, maxX : Float, minY : Float, maxY : Float }"
                        ]
                    ]
                ]
            },
            {
                "name": "BoundingBox3d",
                "comment": " ![BoundingBox3d](https://opensolid.github.io/images/geometry/icons/boundingBox3d.svg)\n\nA bounding box in 3D, defined by its minimum and maximum X, Y and Z values. See\nthe [`BoundingBox3d`](OpenSolid-BoundingBox3d) module for details.\n",
                "args": [],
                "cases": [
                    [
                        "BoundingBox3d",
                        [
                            "{ minX : Float, maxX : Float, minY : Float, maxY : Float, minZ : Float, maxZ : Float }"
                        ]
                    ]
                ]
            },
            {
                "name": "Circle2d",
                "comment": " ![Circle2d](https://opensolid.github.io/images/geometry/icons/circle2d.svg)\n\nA circle in 2D, defined by its center point and radius. See the [`Circle2d`](OpenSolid-Circle2d)\nmodule for details.\n",
                "args": [],
                "cases": [
                    [
                        "Circle2d",
                        [
                            "{ centerPoint : Point2d, radius : Float }"
                        ]
                    ]
                ]
            },
            {
                "name": "Direction2d",
                "comment": " ![Direction2d](https://opensolid.github.io/images/geometry/icons/direction2d.svg)\n\nA direction in 2D, defined by its X and Y components. See the [`Direction2d`](OpenSolid-Direction2d)\nmodule for details.\n",
                "args": [],
                "cases": [
                    [
                        "Direction2d",
                        [
                            "( Float, Float )"
                        ]
                    ]
                ]
            },
            {
                "name": "Direction3d",
                "comment": " ![Direction3d](https://opensolid.github.io/images/geometry/icons/direction3d.svg)\n\nA direction in 3D, defined by its X, Y and Z components. See the [`Direction3d`](OpenSolid-Direction3d)\nmodule for details.\n",
                "args": [],
                "cases": [
                    [
                        "Direction3d",
                        [
                            "( Float, Float, Float )"
                        ]
                    ]
                ]
            },
            {
                "name": "Frame2d",
                "comment": " ![Frame2d](https://opensolid.github.io/images/geometry/icons/frame2d.svg)\n\nA coordinate system in 2D space, defined by its origin point and X and Y\ndirections. See the [`Frame2d`](OpenSolid-Frame2d) module for details.\n",
                "args": [],
                "cases": [
                    [
                        "Frame2d",
                        [
                            "{ originPoint : Point2d, xDirection : Direction2d, yDirection : Direction2d }"
                        ]
                    ]
                ]
            },
            {
                "name": "Frame3d",
                "comment": " ![Frame3d](https://opensolid.github.io/images/geometry/icons/frame3d.svg)\n\nA coordinate system in 3D space, defined by its origin point and X, Y and Z\ndirections. See the [`Frame3d`](OpenSolid-Frame3d) module for details.\n",
                "args": [],
                "cases": [
                    [
                        "Frame3d",
                        [
                            "{ originPoint : Point3d, xDirection : Direction3d, yDirection : Direction3d, zDirection : Direction3d }"
                        ]
                    ]
                ]
            },
            {
                "name": "LineSegment2d",
                "comment": " ![LineSegment2d](https://opensolid.github.io/images/geometry/icons/lineSegment2d.svg)\n\nA line segment in 2D, defined by its start and end points. See the\n[`LineSegment2d`](OpenSolid-LineSegment2d) module for details.\n",
                "args": [],
                "cases": [
                    [
                        "LineSegment2d",
                        [
                            "( Point2d, Point2d )"
                        ]
                    ]
                ]
            },
            {
                "name": "LineSegment3d",
                "comment": " ![LineSegment3d](https://opensolid.github.io/images/geometry/icons/lineSegment3d.svg)\n\nA line segment in 3D, defined by its start and end points. See the\n[`LineSegment3d`](OpenSolid-LineSegment3d) module for details.\n",
                "args": [],
                "cases": [
                    [
                        "LineSegment3d",
                        [
                            "( Point3d, Point3d )"
                        ]
                    ]
                ]
            },
            {
                "name": "Plane3d",
                "comment": " ![Plane3d](https://opensolid.github.io/images/geometry/icons/plane3d.svg)\n\nA plane in 3D, defined by its origin point and normal direction. See the\n[`Plane3d`](OpenSolid-Plane3d) module for details.\n",
                "args": [],
                "cases": [
                    [
                        "Plane3d",
                        [
                            "{ originPoint : Point3d, normalDirection : Direction3d }"
                        ]
                    ]
                ]
            },
            {
                "name": "Point2d",
                "comment": " ![Point2d](https://opensolid.github.io/images/geometry/icons/point2d.svg)\n\nA point in 2D, defined by its X and Y coordinates. See the [`Point2d`](OpenSolid-Point2d)\nmodule for details.\n",
                "args": [],
                "cases": [
                    [
                        "Point2d",
                        [
                            "( Float, Float )"
                        ]
                    ]
                ]
            },
            {
                "name": "Point3d",
                "comment": " ![Point3d](https://opensolid.github.io/images/geometry/icons/point3d.svg)\n\nA point in 3D, defined by its X, Y and Z coordinates. See the [`Point3d`](OpenSolid-Point3d)\nmodule for details.\n",
                "args": [],
                "cases": [
                    [
                        "Point3d",
                        [
                            "( Float, Float, Float )"
                        ]
                    ]
                ]
            },
            {
                "name": "Polygon2d",
                "comment": " ![Polygon2d](https://opensolid.github.io/images/geometry/icons/polygon2d.svg)\n\nA polygon in 2D, defined by a list of vertices. Very similar to a `Polyline2d`\nbut the last point is implicitly considered to connect back to the first point.\nSee the [`Polygon2d`](OpenSolid-Polygon2d) module for details.\n",
                "args": [],
                "cases": [
                    [
                        "Polygon2d",
                        [
                            "List Point2d"
                        ]
                    ]
                ]
            },
            {
                "name": "Polyline2d",
                "comment": " ![Polyline2d](https://opensolid.github.io/images/geometry/icons/polyline2d.svg)\n\nA polyline in 2D, defined by a list of vertices. See the [`Polyline2d`](OpenSolid-Polyline2d)\nmodule for details.\n",
                "args": [],
                "cases": [
                    [
                        "Polyline2d",
                        [
                            "List Point2d"
                        ]
                    ]
                ]
            },
            {
                "name": "Polyline3d",
                "comment": " ![Polyline3d](https://opensolid.github.io/images/geometry/icons/polyline3d.svg)\n\nA polyline in 3D, defined by a list of vertices. See the [`Polyline3d`](OpenSolid-Polyline3d)\nmodule for details.\n",
                "args": [],
                "cases": [
                    [
                        "Polyline3d",
                        [
                            "List Point3d"
                        ]
                    ]
                ]
            },
            {
                "name": "SketchPlane3d",
                "comment": " ![SketchPlane3d](https://opensolid.github.io/images/geometry/icons/sketchPlane3d.svg)\n\nA 2D planar coordinate system embedded in 3D space, defined by its origin point\nand X and Y directions. Used for operations such as projecting 3D geometry into\na 2D coordinate system or placing 2D geometry in 3D. See the [`SketchPlane3d`](OpenSolid-SketchPlane3d)\nmodule for details.\n",
                "args": [],
                "cases": [
                    [
                        "SketchPlane3d",
                        [
                            "{ originPoint : Point3d, xDirection : Direction3d, yDirection : Direction3d }"
                        ]
                    ]
                ]
            },
            {
                "name": "Triangle2d",
                "comment": " ![Triangle2d](https://opensolid.github.io/images/geometry/icons/triangle2d.svg)\n\nA triangle in 2D, defined by its three vertices. See the [`Triangle2d`](OpenSolid-Triangle2d)\nmodule for details.\n",
                "args": [],
                "cases": [
                    [
                        "Triangle2d",
                        [
                            "( Point2d, Point2d, Point2d )"
                        ]
                    ]
                ]
            },
            {
                "name": "Triangle3d",
                "comment": " ![Triangle3d](https://opensolid.github.io/images/geometry/icons/triangle3d.svg)\n\nA triangle in 3D, defined by its three vertices. See the [`Triangle3d`](OpenSolid-Triangle3d)\nmodule for details.\n",
                "args": [],
                "cases": [
                    [
                        "Triangle3d",
                        [
                            "( Point3d, Point3d, Point3d )"
                        ]
                    ]
                ]
            },
            {
                "name": "Vector2d",
                "comment": " ![Vector2d](https://opensolid.github.io/images/geometry/icons/vector2d.svg)\n\nA vector in 2D, defined by its X and Y components. See the [`Vector2d`](OpenSolid-Vector2d)\nmodule for details.\n",
                "args": [],
                "cases": [
                    [
                        "Vector2d",
                        [
                            "( Float, Float )"
                        ]
                    ]
                ]
            },
            {
                "name": "Vector3d",
                "comment": " ![Vector3d](https://opensolid.github.io/images/geometry/icons/vector3d.svg)\n\nA vector in 3D, defined by its X, Y and Z components. See the [`Vector3d`](OpenSolid-Vector3d)\nmodule for details.\n",
                "args": [],
                "cases": [
                    [
                        "Vector3d",
                        [
                            "( Float, Float, Float )"
                        ]
                    ]
                ]
            }
        ],
        "aliases": [],
        "values": [],
        "binops": []
    }
]