/geometry

2D/3D geometry package for Elm

Primary LanguageElmMozilla Public License 2.0MPL-2.0

opensolid/geometry Travis build Status

Note: if you're upgrading from 1.x, make sure to check out the release notes!

opensolid/geometry is an Elm package for working with 2D and 3D geometry. It provides a wide variety of geometric data types such as points, vectors, arcs, spline curves and coordinate frames, along with functions for transforming and combining them in many different ways. You can:

  • Rotate points around axes in 3D
  • Mirror triangles across 3D planes
  • Project 3D geometry into 2D sketch planes
  • Measure distances and angles between different objects
  • Convert objects between different coordinate systems
  • Compose complex 2D/3D transformations
  • ...and much more!

A wide variety of data types are supported:

  • Point2d, Point3d, Vector2d, Vector3d, Direction2d, Direction3d

    Point2d Point3d Vector2d Vector3d Direction2d Direction3d

  • Axis2d, Axis3d, Plane3d

    Axis2d Axis3d Plane3d

  • Frame2d, Frame3d, SketchPlane3d

    Frame2d Frame3d SketchPlane3d

  • BoundingBox2d, BoundingBox3d

    BoundingBox2d BoundingBox3d

  • LineSegment2d, LineSegment3d, Triangle2d, Triangle3d

    LineSegment2d LineSegment3d Triangle2d Triangle3d

  • Polyline2d, Polyline3d, Polygon2d

    Polyline2d Polyline3d Polygon2d

  • Circle2d, Circle3d, Arc2d, Arc3d

    Circle2d Circle3d Arc2d Arc3d

  • QuadraticSpline2d, QuadraticSpline3d, CubicSpline2d, CubicSpline3d

    QuadraticSpline2d QuadraticSpline3d CubicSpline2d CubicSpline3d

A large range of geometric functionality is included, such as various forms of constructors...

Point3d.fromCoordinates ( 1, 4, 5 )

Direction2d.fromAngle (degrees 30)

Point3d.midpoint p1 p2

Triangle2d.fromVertices ( p1, p2, p3 )

-- fit a plane through three points
Plane3d.throughPoints ( p1, p2, p3 )

Axis3d.with
    { originPoint = Point3d.origin
    , direction = Direction3d.z
    }

Arc2d.fromEndpoints
    { startPoint = p1
    , endPoint = p2
    , radius = 3
    , sweptAngle = Arc2d.smallPositive
    }

QuadraticSpline3d.fromControlPoints ( p1, p2, p3 )

CubicSpline2d.hermite
    ( startPoint, startDerivative )
    ( endPoint, endDerivative )

...point/vector arithmetic...

Vector3d.sum v1 v2

-- the vector from the point p1 to the point p2
Vector2d.from p1 p2

Vector3d.crossProduct v1 v2

Vector2d.length vector

-- distance of a point from the origin point (0, 0)
point |> Point2d.distanceFrom Point2d.origin

...2D/3D transformations...

Vector2d.rotateBy (degrees 45) vector

Point2d.rotateAround Point2d.origin (degrees 45) point

Point3d.mirrorAcross Plane3d.xy point

Vector3d.projectionIn Direction3d.z vector

Triangle3d.rotateAround Axis3d.x (degrees 45) triangle

lineSegment
    |> LineSegment3d.mirrorAcross Plane3d.yz
    |> LineSegment3d.projectOnto Plane3d.xy

Plane3d.offsetBy 3 Plane3d.xy

...and conversions between coordinate systems:

rotatedFrame =
    Frame2d.xy |> Frame2d.rotateBy (degrees 30)

-- convert from global coordinates to local coordinates
-- (relative to the given coordinate frame)
Vector2d.relativeTo rotatedFrame vector

-- convert from local coordinates (relative to the given
-- coordinate frame) to global coordinates
Point2d.placeIn rotatedFrame point

-- convert from global 3D coordinates to local 2D
-- coordinates in the given sketch plane
point2d =
    Point3d.projectInto SketchPlane3d.yz point3d

-- convert from local 2D coordinates in the given
-- sketch plane back to global 3D coordinates
point3d =
    Point3d.on SketchPlane3d.yz point2d

Support is also provided for encoding/decoding values to and from JSON.

Installation

Assuming you have installed Elm and started a new project, use elm-package to install opensolid/geometry, either by running

elm package install opensolid/geometry

in a command prompt inside your project directory or by adding

"opensolid/geometry": "2.0.0 <= v < 3.0.0"

to the dependencies field in your project's elm-package.json.

Documentation

Full API documentation is available for each module. Most modules are associated with a particular data type (for example, the Point3d module contains functions for creating and manipulating Point3d values).

Usage details

Following the Elm package design guidelines, most OpenSolid modules are designed to be imported using as and then used as prefixes for the functions and values that they define. Types are designed to be imported unqualified using exposing:

import OpenSolid.Point3d as Point3d exposing (Point3d)
import OpenSolid.Axis3d as Axis3d exposing (Axis3d)

rotatedPoint : Point3d
rotatedPoint =
    Point3d.rotateAround Axis3d.x (degrees 30) originalPoint

Related projects

Questions? Comments?

Please open a new issue if you run into a bug, if any documentation is missing/incorrect/confusing, or if there's a new feature that you would find useful. For general questions about using OpenSolid, try:

  • Sending me (@ianmackenzie) a message on the Elm Slack - even if you don't have any particular questions right now, just come say hello!
  • Posting to the r/elm subreddit
  • Posting to the elm-discuss Google Group (somewhat less active than Slack and Reddit, but I still follow it regularly if you prefer e-mail)
  • Or if you happen to be in the New York area, come on out to the Elm NYC meetup =)

You can also find me on Twitter (@ianemackenzie), where I occasionally post OpenSolid-related stuff like demos or new releases. Have fun, and don't be afraid to ask for help!