• Stars
    star
    183
  • Rank 210,154 (Top 5 %)
  • Language
    Elm
  • License
    Mozilla Public Li...
  • Created over 8 years ago
  • Updated 4 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

2D/3D geometry package for Elm

elm-geometry

Release notes for all versions of elm-geometry are available here.

elm-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!

Table of contents

Overview

elm-geometry includes a wide variety of data types: points, vectors, directions...

Point2d Point3d Vector2d Vector3d Direction2d Direction3d

...line segments, triangles, bounding boxes...

LineSegment2d LineSegment3d Triangle2d Triangle3d BoundingBox2d BoundingBox3d

...polylines, polygons, quadratic and cubic splines...

Polyline2d Polyline3d Polygon2d QuadraticSpline2d QuadraticSpline3d CubicSpline2d CubicSpline3d

...circles, arcs, ellipses and elliptical arcs...

Circle2d Circle3d Arc2d Arc3d Ellipse2d EllipticalArc2d

...plus axes, planes, and various forms of 2D/3D coordinate systems:

Axis2d Axis3d Plane3d Frame2d Frame3d SketchPlane3d

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

Point3d.xyz
    (Length.meters 2)
    (Length.meters 4)
    (Length.meters 5)
-- OR --
Point3d.meters 2 4 5

Direction2d.fromAngle (Angle.degrees 30)
-- OR --
Direction2d.degrees 30

Point3d.midpoint p1 p2

Vector2d.withLength (Length.feet 3) Direction2d.y

Triangle2d.fromVertices ( p1, p2, p3 )
-- OR --
Triangle2d.from p1 p2 p3

Plane3d.throughPoints p1 p2 p3

Axis3d.through Point3d.origin Direction3d.z

Arc2d.from p1 p2 (Angle.degrees 90)

QuadraticSpline3d.fromControlPoints p1 p2 p3

CubicSpline2d.fromEndpoints
    startPoint
    startDerivative
    endPoint
    endDerivative

...point/vector arithmetic...

v1 |> Vector3d.plus v2

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

v1 |> Vector3d.cross v2

Vector2d.length vector

-- distance of a point from the origin
point |> Point2d.distanceFrom Point2d.origin

...and 2D/3D transformations:

vector |> Vector2d.rotateBy angle

point |> Point2d.rotateAround Point2d.origin angle

point |> Point3d.mirrorAcross Plane3d.xy

vector |> Vector3d.projectionIn Direction3d.z

triangle |> Triangle3d.rotateAround Axis3d.x angle

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

Plane3d.xy |> Plane3d.offsetBy (Length.meters 3)

Units and coordinate systems

Most types in elm-geometry include two phantom type parameters that allow compile-time tracking of both what units that geometry is in (usually either meters for real-world geometry, or pixels for on-screen geometry) and what coordinate system the geometry is defined in. For example, you might use a

Point2d Pixels YUpCoordinates

to represent a point on the screen that is defined in Y-up coordinates (from the lower-left corner of an SVG drawing, for example) as opposed to Y-down coordinates from the top left corner of the screen.

Units

elm-geometry uses the Quantity type from elm-units to track/convert the units associated with numeric values such as point coordinates, vector components, lengths, distances and angles. Internally, elm-units converts everything to SI units, so

Point2d.inches 10 20

and

Point2d.centimeters 25.4 50.8

are equivalent. Tracking units at compile time prevents mixing and matching different types of geometry; for example,

Point2d.xy (Length.meters 3) (Length.meters 4)

and

Point2d.xy (Pixels.pixels 200) (Pixels.pixels 300)

have completely different units, so the compiler can catch nonsensical operations like trying to find the distance from the first point to the second.

Coordinate systems

2D/3D geometry is often represented using X/Y/Z coordinates. As a result, in addition to tracking which units are used, elm-geometry also lets you add type annotations to specify what coordinate system particular geometry is defined in. For example, we might declare a TopLeftCoordinates type and then add a type annotation to a point asserting that it is defined in coordinates relative to the top-left corner of the screen:

{-| A coordinate system where (0, 0) is the top left corner
of the screen, positive X is to the right, and positive Y
is down.
-}
type TopLeftCoordinates =
    TopLeftCoordinates

point : Point2d Pixels TopLeftCoordinates
point =
    Point2d.pixels 200 300

Note that the TopLeftCoordinates type we declared gives us a convenient place to document exactly how that coordinate system is defined. This combination now gives us some nice type safety - the compiler will tell us if we try to mix two points that have different units or are defined in different coordinate systems.

Installation

Assuming you have installed Elm and started a new project, you'll want to run

elm install ianmackenzie/elm-geometry
elm install ianmackenzie/elm-units

in a command prompt inside your project directory. Note that even though elm-units is a dependency of elm-geometry, you'll still need to explicitly install it so that you can import modules like Quantity and Length in your own code (which will be needed in basically any code that uses elm-geometry.)

Using the package

By itself, elm-geometry only performs abstract geometric operations like measurements (distances, areas), checks (containment, intersection) and transformations (scaling, rotation, translation, mirroring). See the related packages section below for links to some packages that build on top of elm-geometry to perform 2D drawing, 3D rendering, physics simulation etc.

In general when using elm-geometry, you'll need to import a module for every different data type that you want to work with; there is no "main" module. For example, to calculate the distance between two 2D points, you would import the Point2d module and write something like:

module Main exposing (main)

import Html exposing (Html)
import Length -- from elm-units, see 'Installation'
import Point2d

main : Html msg
main =
    let
        firstPoint =
            Point2d.meters 1 2

        secondPoint =
            Point2d.meters 3 4

        distanceInCentimeters =
            Point2d.distanceFrom firstPoint secondPoint
                |> Length.inCentimeters
    in
    Html.text <|
        "Distance: "
            ++ String.fromInt (round distanceInCentimeters)
            ++ " cm"

which should end up displaying "Distance: 283 cm".

Note that it was necessary to also import the Length module from elm-units, since the Point2d.distanceFrom function returns a Quantity Float units, not a plain Float. In general, in addition to elm-geometry modules, you'll likely need to import either the Length or Pixels modules from elm-units (depending on whether you're working in real-world or on-screen units) to work with any individual values returned by elm-geometry functions (distances, areas, point coordinates, vector components, etc.).

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).

Related packages

There are several other Elm packages related to elm-geometry:

I'm hopeful that in the future there will be packages that build on elm-geometry to do non-graphical things like 3D printing or CNC machining!

Climate action

I would like for the projects I work on to be as helpful as possible in addressing the climate crisis. If

  • you are working on a project that helps address the climate crisis (clean energy, public transit, reforestation, sustainable agriculture etc.) either as an individual, as part of an non-profit organization or even as part of a for-profit company, and
  • there is a new feature you would find helpful for that work (or a bug you need fixed) in any of my open-source projects, then

please open a new issue, describe briefly what you're working on and I will treat that issue as high priority.

Questions and feedback

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 elm-geometry, the best place is probably the #geometry channel on the friendly Elm Slack:

Elm Slack #geometry channel conversation

You can also try:

  • Sending me (@ianmackenzie) a message on Slack - even if you don't have any particular questions right now, it would be great to know what you're hoping to do with the package!
  • Posting to the Elm Discourse forums

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

More Repositories

1

elm-3d-scene

A high-level 3D rendering engine for Elm, with support for lighting, shadows, and realistic materials.
Elm
207
star
2

elm-units

Simple, safe and convenient unit types and conversions for Elm
Elm
84
star
3

elm-geometry-svg

Render 2D elm-geometry types as SVG
Elm
46
star
4

elm-script

Experimental command-line scripting for Elm
Elm
34
star
5

elm-3d-camera

Camera type for doing 3D rendering in Elm
Elm
12
star
6

elm-iso-10303

Create data in ISO 10303-21 (STEP file) format
Elm
10
star
7

elm-triangular-mesh

Generic indexed triangular mesh data structure for Elm
Elm
8
star
8

elm-2d-drawing

Elm
6
star
9

elm-float-extra

Useful functionality for Float values in Elm
Elm
3
star
10

elm-interval

Simple Interval type for Elm
Elm
2
star
11

polyhedron-edges

Elm
2
star
12

shift-keys

Simple utility for counting shift key use
Elm
1
star
13

opensolid-diagram

SVG-based diagramming package used to produce OpenSolid documentation illustrations
Elm
1
star
14

opensolid-geometry-scala

Scala implementation of opensolid/geometry
Scala
1
star
15

elm-geometry-prerelease

Elm
1
star
16

elm-geometry-extra

Extra community-contributed functionality for elm-geometry
Elm
1
star
17

scripts

Elm
1
star
18

ads-elm-intro

Introductory Elm examples for ADS lunchtime talk
Elm
1
star
19

elm-units-interval

Version of elm-interval based on elm-units
Elm
1
star
20

elm-1d-parameter

Generate evenly spaced interpolated values in Elm
Elm
1
star
21

elm-geometry-linear-algebra-interop

Interop support for ianmackenzie/elm-geometry and elm-community/linear-algebra
Elm
1
star
22

elm-random-test

Small helpers for using elm-test with Generators instead of Fuzzers
Elm
1
star