{"id":13561704,"url":"https://github.com/ianmackenzie/elm-geometry","last_synced_at":"2025-04-06T01:11:27.450Z","repository":{"id":45126779,"uuid":"65344250","full_name":"ianmackenzie/elm-geometry","owner":"ianmackenzie","description":"2D/3D geometry package for Elm","archived":false,"fork":false,"pushed_at":"2024-07-27T00:35:06.000Z","size":4644,"stargazers_count":185,"open_issues_count":47,"forks_count":26,"subscribers_count":11,"default_branch":"main","last_synced_at":"2025-03-30T00:08:32.418Z","etag":null,"topics":["cad","coordinate-systems","curve","elm","geometry","hacktoberfest","point","transformations","vector"],"latest_commit_sha":null,"homepage":"","language":"Elm","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ianmackenzie.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":"AUTHORS","dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-08-10T02:37:26.000Z","updated_at":"2025-03-18T07:35:29.000Z","dependencies_parsed_at":"2022-08-26T10:41:01.171Z","dependency_job_id":"e95b8669-a2ff-4098-8a63-64ab5dd33ee3","html_url":"https://github.com/ianmackenzie/elm-geometry","commit_stats":{"total_commits":2964,"total_committers":19,"mean_commits":156.0,"dds":0.0560053981106613,"last_synced_commit":"aa2150669f26e89086c79a176670401036478473"},"previous_names":[],"tags_count":24,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ianmackenzie%2Felm-geometry","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ianmackenzie%2Felm-geometry/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ianmackenzie%2Felm-geometry/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ianmackenzie%2Felm-geometry/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ianmackenzie","download_url":"https://codeload.github.com/ianmackenzie/elm-geometry/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247419866,"owners_count":20936013,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cad","coordinate-systems","curve","elm","geometry","hacktoberfest","point","transformations","vector"],"created_at":"2024-08-01T13:01:00.164Z","updated_at":"2025-04-06T01:11:27.428Z","avatar_url":"https://github.com/ianmackenzie.png","language":"Elm","funding_links":[],"categories":["Elm"],"sub_categories":[],"readme":"# elm-geometry\n\n_Release notes for all versions of `elm-geometry` are available\n[here](https://github.com/ianmackenzie/elm-geometry/releases)._\n\n⚠️ **NOTE**: Currently you probably want to use `elm-geometry` 3.11 instead\nif you're using `elm-3d-scene`, since `elm-3d-scene` has not yet been\nupdated to use `elm-geometry` 4.0. The next release of `elm-3d-scene`\nwill be updated to use `elm-geometry` 4.0.\n\n`elm-geometry` is an [Elm](http://elm-lang.org) package for working with 2D and\n3D geometry. It provides a wide variety of geometric data types such as points,\nvectors, arcs, spline curves and coordinate frames, along with functions for\ntransforming and combining them in many different ways. You can:\n\n- Rotate points around axes in 3D\n- Mirror triangles across 3D planes\n- Project 3D geometry into 2D sketch planes\n- Measure distances and angles between different objects\n- Convert objects between different coordinate systems\n- Compose complex 2D/3D transformations\n- ...and much more!\n\n## Table of contents\n\n- [Overview](#overview)\n- [Units and coordinate systems](#units-and-coordinate-systems)\n  - [Units](#units)\n  - [Coordinate systems](#coordinate-systems)\n  - [Conversions](#conversions)\n- [Installation](#installation)\n- [Using the package](#using-the-package)\n- [Documentation](#documentation)\n- [Related packages](#related-packages)\n- [Climate action](#climate-action)\n- [Questions and feedback](#questions-and-feedback)\n\n## Overview\n\n`elm-geometry` includes a wide variety of data types: points, vectors, directions...\n\n![Point2d](https://opensolid.github.io/images/geometry/icons/point2d.svg)\n![Point3d](https://opensolid.github.io/images/geometry/icons/point3d.svg)\n![Vector2d](https://opensolid.github.io/images/geometry/icons/vector2d.svg)\n![Vector3d](https://opensolid.github.io/images/geometry/icons/vector3d.svg)\n![Direction2d](https://opensolid.github.io/images/geometry/icons/direction2d.svg)\n![Direction3d](https://opensolid.github.io/images/geometry/icons/direction3d.svg)\n\n...line segments, triangles, bounding boxes...\n\n![LineSegment2d](https://opensolid.github.io/images/geometry/icons/lineSegment2d.svg)\n![LineSegment3d](https://opensolid.github.io/images/geometry/icons/lineSegment3d.svg)\n![Triangle2d](https://opensolid.github.io/images/geometry/icons/triangle2d.svg)\n![Triangle3d](https://opensolid.github.io/images/geometry/icons/triangle3d.svg)\n![BoundingBox2d](https://opensolid.github.io/images/geometry/icons/boundingBox2d.svg)\n![BoundingBox3d](https://opensolid.github.io/images/geometry/icons/boundingBox3d.svg)\n\n...polylines, polygons, quadratic and cubic splines...\n\n![Polyline2d](https://opensolid.github.io/images/geometry/icons/polyline2d.svg)\n![Polyline3d](https://opensolid.github.io/images/geometry/icons/polyline3d.svg)\n![Polygon2d](https://opensolid.github.io/images/geometry/icons/polygon2d.svg)\n![QuadraticSpline2d](https://opensolid.github.io/images/geometry/icons/quadraticSpline2d.svg)\n![QuadraticSpline3d](https://opensolid.github.io/images/geometry/icons/quadraticSpline3d.svg)\n![CubicSpline2d](https://opensolid.github.io/images/geometry/icons/cubicSpline2d.svg)\n![CubicSpline3d](https://opensolid.github.io/images/geometry/icons/cubicSpline3d.svg)\n\n...circles, arcs, ellipses and elliptical arcs...\n\n![Circle2d](https://opensolid.github.io/images/geometry/icons/circle2d.svg)\n![Circle3d](https://opensolid.github.io/images/geometry/icons/circle3d.svg)\n![Arc2d](https://opensolid.github.io/images/geometry/icons/arc2d.svg)\n![Arc3d](https://opensolid.github.io/images/geometry/icons/arc3d.svg)\n![Ellipse2d](https://opensolid.github.io/images/geometry/icons/ellipse2d.svg)\n![EllipticalArc2d](https://opensolid.github.io/images/geometry/icons/ellipticalArc2d.svg)\n\n...plus axes, planes, and various forms of 2D/3D coordinate systems:\n\n![Axis2d](https://opensolid.github.io/images/geometry/icons/axis2d.svg)\n![Axis3d](https://opensolid.github.io/images/geometry/icons/axis3d.svg)\n![Plane3d](https://opensolid.github.io/images/geometry/icons/plane3d.svg)\n![Frame2d](https://opensolid.github.io/images/geometry/icons/frame2d.svg)\n![Frame3d](https://opensolid.github.io/images/geometry/icons/frame3d.svg)\n![SketchPlane3d](https://opensolid.github.io/images/geometry/icons/sketchPlane3d.svg)\n\nA large range of geometric functionality is included, such as various forms of\nconstructors...\n\n```elm\nPoint3d.xyz\n    (Length.meters 2)\n    (Length.meters 4)\n    (Length.meters 5)\n-- OR --\nPoint3d.meters 2 4 5\n\nDirection2d.fromAngle (Angle.degrees 30)\n-- OR --\nDirection2d.degrees 30\n\nPoint3d.midpoint p1 p2\n\nVector2d.withLength (Length.feet 3) Direction2d.y\n\nTriangle2d.fromVertices ( p1, p2, p3 )\n-- OR --\nTriangle2d.from p1 p2 p3\n\nPlane3d.throughPoints p1 p2 p3\n\nAxis3d.through Point3d.origin Direction3d.z\n\nArc2d.from p1 p2 (Angle.degrees 90)\n\nQuadraticSpline3d.fromControlPoints p1 p2 p3\n\nCubicSpline2d.fromEndpoints\n    startPoint\n    startDerivative\n    endPoint\n    endDerivative\n```\n\n...point/vector arithmetic...\n\n```elm\nv1 |\u003e Vector3d.plus v2\n\n-- the vector from the point p1 to the point p2\nVector2d.from p1 p2\n\nv1 |\u003e Vector3d.cross v2\n\nVector2d.length vector\n\n-- distance of a point from the origin\npoint |\u003e Point2d.distanceFrom Point2d.origin\n```\n\n...and 2D/3D transformations:\n\n```elm\nvector |\u003e Vector2d.rotateBy angle\n\npoint |\u003e Point2d.rotateAround Point2d.origin angle\n\npoint |\u003e Point3d.mirrorAcross Plane3d.xy\n\nvector |\u003e Vector3d.projectionIn Direction3d.z\n\ntriangle |\u003e Triangle3d.rotateAround Axis3d.x angle\n\nlineSegment\n    |\u003e LineSegment3d.mirrorAcross Plane3d.yz\n    |\u003e LineSegment3d.projectOnto Plane3d.xy\n\nPlane3d.xy |\u003e Plane3d.offsetBy (Length.meters 3)\n```\n\n## Units and coordinate systems\n\nMost types in `elm-geometry` include two [phantom type parameters](https://blog.ilias.xyz/5-things-you-didnt-know-about-elm-7bdb67b1b3cd#ea40)\nthat allow compile-time tracking of both what units that geometry is in (usually\neither meters for real-world geometry, or pixels for on-screen geometry) and\nwhat coordinate system the geometry is defined in. For example, you might use a\n\n```elm\nPoint2d Pixels YUpCoordinates\n```\n\nto represent a point on the screen that is defined in Y-up coordinates (from\nthe lower-left corner of an SVG drawing, for example) as opposed to Y-down\ncoordinates from the top left corner of the screen.\n\n### Units\n\n`elm-geometry` uses the `Quantity` type from [`elm-units`](https://package.elm-lang.org/packages/ianmackenzie/elm-units/latest) to track/convert the units associated with\nnumeric values such as point coordinates, vector components, lengths, distances\nand angles. Internally, `elm-units` converts everything to [SI](https://en.wikipedia.org/wiki/International_System_of_Units)\nunits, so\n\n```elm\nPoint2d.inches 10 20\n```\n\nand\n\n```elm\nPoint2d.centimeters 25.4 50.8\n```\n\nare equivalent. Tracking units at compile time prevents mixing and matching\ndifferent types of geometry; for example,\n\n```elm\nPoint2d.xy (Length.meters 3) (Length.meters 4)\n```\n\nand\n\n```elm\nPoint2d.xy (Pixels.pixels 200) (Pixels.pixels 300)\n```\n\nhave completely different units, so the compiler can catch nonsensical\noperations like trying to find the distance from the first point to the second.\n\n### Coordinate systems\n\n2D/3D geometry is often represented using X/Y/Z coordinates. As a result, in\naddition to tracking which units are used, `elm-geometry` also lets you add type\nannotations to specify what _coordinate system_ particular geometry is defined\nin. For example, we might declare a `TopLeftCoordinates` type and then add a\ntype annotation to a `point` asserting that it is defined in coordinates\nrelative to the top-left corner of the screen:\n\n```elm\n{-| A coordinate system where (0, 0) is the top left corner\nof the screen, positive X is to the right, and positive Y\nis down.\n-}\ntype TopLeftCoordinates =\n    TopLeftCoordinates\n\npoint : Point2d Pixels TopLeftCoordinates\npoint =\n    Point2d.pixels 200 300\n```\n\nNote that the `TopLeftCoordinates` type we declared gives us a convenient place\nto document exactly how that coordinate system is defined. This combination now\ngives us some nice type safety - the compiler will tell us if we try to mix two\npoints that have different units or are defined in different coordinate systems.\n\n## Installation\n\nAssuming you have [installed Elm](https://guide.elm-lang.org/install.html) and\nstarted a new project, you'll want to run\n\n```text\nelm install ianmackenzie/elm-geometry\nelm install ianmackenzie/elm-units\n```\n\nin a command prompt inside your project directory. Note that even though\n`elm-units` is a dependency of `elm-geometry`, you'll still need to explicitly\ninstall it so that you can import modules like [`Quantity`](https://package.elm-lang.org/packages/ianmackenzie/elm-units/latest/Quantity)\nand [`Length`](https://package.elm-lang.org/packages/ianmackenzie/elm-units/latest/Length)\nin your own code (which will be needed in basically any code that uses\n`elm-geometry`.)\n\n## Using the package\n\nBy itself, `elm-geometry` only performs abstract geometric operations like\nmeasurements (distances, areas), checks (containment, intersection) and\ntransformations (scaling, rotation, translation, mirroring). See the [related\npackages](#related-packages) section below for links to some packages that build\non top of `elm-geometry` to perform 2D drawing, 3D rendering, physics simulation\netc.\n\nIn general when using `elm-geometry`, you'll need to import a module for every\ndifferent data type that you want to work with; there is no \"main\" module. For\nexample, to calculate the distance between two 2D points, you would import the\n`Point2d` module and write something like:\n\n```elm\nmodule Main exposing (main)\n\nimport Html exposing (Html)\nimport Length -- from elm-units, see 'Installation'\nimport Point2d\n\nmain : Html msg\nmain =\n    let\n        firstPoint =\n            Point2d.meters 1 2\n\n        secondPoint =\n            Point2d.meters 3 4\n\n        distanceInCentimeters =\n            Point2d.distanceFrom firstPoint secondPoint\n                |\u003e Length.inCentimeters\n    in\n    Html.text \u003c|\n        \"Distance: \"\n            ++ String.fromInt (round distanceInCentimeters)\n            ++ \" cm\"\n```\n\nwhich should end up displaying \"Distance: 283 cm\".\n\nNote that it was necessary to also import the [`Length`](https://package.elm-lang.org/packages/ianmackenzie/elm-units/latest/Length)\nmodule from [`elm-units`](https://package.elm-lang.org/packages/ianmackenzie/elm-units/latest/),\nsince the [`Point2d.distanceFrom`](https://package.elm-lang.org/packages/ianmackenzie/elm-geometry/latest/Point2d#distanceFrom)\nfunction returns a [`Quantity Float units`](https://package.elm-lang.org/packages/ianmackenzie/elm-units/latest/Quantity#Quantity),\nnot a plain `Float`. In general, in addition to `elm-geometry` modules, you'll\nlikely need to import either the `Length` or [`Pixels`](https://package.elm-lang.org/packages/ianmackenzie/elm-units/latest/Pixels)\nmodules from `elm-units` (depending on whether you're working in real-world or\non-screen units) to work with any individual values returned by `elm-geometry`\nfunctions (distances, areas, point coordinates, vector components, etc.).\n\n## Documentation\n\n[Full API documentation](https://package.elm-lang.org/packages/ianmackenzie/elm-geometry/latest)\nis available for each module. Most modules are associated with a particular data\ntype (for example, the [`Point3d`](https://package.elm-lang.org/packages/ianmackenzie/elm-geometry/latest/Point3d)\nmodule contains functions for creating and manipulating `Point3d` values).\n\n## Related packages\n\nThere are several other Elm packages related to `elm-geometry`:\n\n- For drawing in 2D, check out [`elm-geometry-svg`](https://package.elm-lang.org/packages/ianmackenzie/elm-geometry-svg/latest/)\n- For 3D graphics, check out [`elm-3d-scene`](https://package.elm-lang.org/packages/ianmackenzie/elm-3d-scene/latest/)\n  for a high-level approach or [`elm-geometry-linear-algebra-interop`](https://package.elm-lang.org/packages/ianmackenzie/elm-geometry-linear-algebra-interop/latest/)\n  and [`elm-3d-camera`](https://package.elm-lang.org/packages/ianmackenzie/elm-3d-camera/latest/)\n  for working with WebGL directly\n- For physics-based simulations/games, [`elm-physics`](https://package.elm-lang.org/packages/w0rm/elm-physics/latest/)\n  is based on `elm-geometry` and provides a 3D physics engine including\n  collisions, gravity, and constraints (joints)\n- The [`elm-1d-parameter`](https://package.elm-lang.org/packages/ianmackenzie/elm-1d-parameter/latest/)\n  package is both used internally by `elm-geometry`, and is useful to combine\n  with functions like [`Point2d.interpolateFrom`](https://package.elm-lang.org/packages/ianmackenzie/elm-geometry/latest/Point2d#interpolateFrom)\n  to generate evenly-spaced values\n- Functions like [`Polygon2d.triangulate`](https://package.elm-lang.org/packages/ianmackenzie/elm-geometry/latest/Polygon2d#triangulate)\n  return their results as a `TriangularMesh` value from [`elm-triangular-mesh`](https://package.elm-lang.org/packages/ianmackenzie/elm-triangular-mesh/latest/)\n\nI'm hopeful that in the future there will be packages that build on\n`elm-geometry` to do non-graphical things like 3D printing or CNC machining!\n\n## Climate action\n\nI would like for the projects I work on to be as helpful as possible in\naddressing the climate crisis. If\n\n- you are working on a project that helps address the climate crisis (clean\n  energy, public transit, reforestation, sustainable agriculture etc.) either as\n  an individual, as part of an non-profit organization or even as part of a\n  for-profit company, and\n- there is a new feature you would find helpful for that work (or a bug you need\n  fixed) in any of my open-source projects, then\n\nplease [open a new issue](https://github.com/ianmackenzie/elm-geometry/issues),\ndescribe briefly what you're working on and I will treat that issue as high\npriority.\n\n## Questions and feedback\n\nPlease [open a new issue](https://github.com/ianmackenzie/elm-geometry/issues)\nif you run into a bug, if any documentation is missing/incorrect/confusing, or\nif there's a new feature that you would find useful. For general questions about\nusing `elm-geometry`, the best place is probably the **#geometry** channel on\nthe friendly [Elm Slack](http://elmlang.herokuapp.com/):\n\n![Elm Slack #geometry channel conversation](https://ianmackenzie.github.io/elm-geometry/1.0.0/README/Slack.png)\n\nYou can also try:\n\n- Sending me (**@ianmackenzie**) a message on Slack - even if you don't have any\n  particular questions right now, it would be great to know what you're hoping\n  to do with the package!\n- Posting to the [Elm Discourse](https://discourse.elm-lang.org/) forums\n\nYou can also find me on Twitter ([@ianemackenzie](https://twitter.com/ianemackenzie)),\nwhere I occasionally post `elm-geometry`-related stuff like demos or new\nreleases. Have fun, and don't be afraid to ask for help!\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fianmackenzie%2Felm-geometry","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fianmackenzie%2Felm-geometry","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fianmackenzie%2Felm-geometry/lists"}