Skip to content
jolarsPublic

About

A Rust library for Euler and Venn Diagrams

Topics

Resources

Contributing

Stars

16 stars

Watchers

1 watching

Forks

Latest commit

 

History

854 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Eunoia

CI Crates.io npm pypi CRAN codecov arXiv DOI

Eunoia is a Rust library for area-proportional Euler and Venn diagrams. Give it a set of sizes and intersections and it fits a layout of shapes whose areas match your data as closely as possible. It is a ground-up rewrite of the R package eulerr: faster, more flexible, and built to power bindings across many languages. Read the documentation at eunoia.bz.

Highlights

  • Five shape families: fit with circles, ellipses, squares, axis-aligned rectangles, or rotated rectangles; the engine is shape-agnostic until fit time.
  • Robust fitting: initial initialization followed by a global/local optimization pipeline that mirrors and improves on eulerr.
  • Venn diagrams too: canonical arrangements for up to three sets with circles, squares, or rectangles, four with rotated rectangles, and five with ellipses, independent of the fitter.
  • Renderable output: region polygon extraction, clipping, and automatic label placement, ready to draw as SVG.
  • Many targets: pure Rust core that ships to JavaScript via WebAssembly and to other languages through a small C ABI.

Quick start (Rust)

cargo add eunoia

Then run the following example to fit an Euler diagram of three overlapping sets.

use eunoia::geometry::shapes::Ellipse;
use eunoia::{DiagramSpecBuilder, Fitter, InputType};

fn main() {
    let spec = DiagramSpecBuilder::new()
        .set("Adventure", 20.0)
        .set("Comedy", 14.0)
        .set("Drama", 18.0)
        .intersection(&["Adventure", "Comedy"], 6.0)
        .intersection(&["Adventure", "Drama"], 5.0)
        .intersection(&["Comedy", "Drama"], 4.0)
        .intersection(&["Adventure", "Comedy", "Drama"], 2.0)
        .input_type(InputType::Exclusive)
        .build()
        .unwrap();

    // Swap `Ellipse` for `Circle`, `Square`, `Rectangle`, or `RotatedRectangle`.
    let layout = Fitter::<Ellipse>::new(&spec).seed(1).fit().unwrap();

    println!(
        "{} shapes, loss = {:.2e}",
        layout.shapes().len(),
        layout.loss()
    );
}

An area-proportional Euler diagram of three overlapping sets labelled Adventure, Comedy, and Drama.

layout.shapes() returns the fitted geometry; the plotting module turns a Layout into region polygons and label anchors for rendering. See the rustdoc for the full API.

Web app

Eunoia powers a web app for interactive diagram fitting and exploration, located at https://eunoia.bz/app.

The Eunoia ecosystem

The pure-Rust core powers bindings in several languages, all backed by the same fitting engine:

Language Package Install
R eulerr (repo) install.packages("eulerr")
Python eunoia (repo) pip install eunoia
Julia Eunoia.jl (repo) ]add Eunoia
JavaScript @jolars/eunoia (this repo) npm install @jolars/eunoia

JavaScript/TypeScript

A TypeScript package is published as @jolars/eunoia. Here's a minimal example of fitting an Euler diagram in Node or a bundler environment:

import { euler, venn } from "@jolars/eunoia";

// Fit an Euler diagram from set sizes
const layout = euler({
  sets: { A: 5, B: 2, "A&B": 1 },
  shape: "circle", // "circle" | "ellipse" | "square" | "rectangle" | "rotatedRectangle"
  output: "shapes", // "shapes" | "polygons" | "regions"
  inputType: "exclusive", // "exclusive" | "inclusive"
  seed: 42,
});

if (layout.mode === "shapes" && layout.shape === "circle") {
  for (const c of layout.circles) {
    console.log(c.label, c.x, c.y, c.radius);
  }
}

// Or build a canonical n-set Venn diagram
const v = venn({ n: 3, output: "regions" });

A renderer-agnostic SVG serializer is available at @jolars/eunoia/svg. The default entry is built with wasm-pack --target bundler, so it works with any modern bundler (Vite, Webpack, Rollup, esbuild) and Node 20+.

Browser/Observable (no Bundler)

The default entry imports the .wasm module directly, which only a bundler can resolve. For a plain HTML page, an Observable notebook, or any environment without a build step, use the @jolars/eunoia/web entry instead: a single self-contained ESM file with the WebAssembly module inlined. Call init() once before fitting:

<script type="module">
  import { euler, init } from "https://esm.sh/@jolars/eunoia/web";

  await init(); // instantiate the embedded WebAssembly module (once)

  const layout = euler({ sets: { A: 5, B: 2, "A&B": 1 } });
  console.log(layout.circles);
</script>

Observable

eunoia = import("https://esm.sh/@jolars/eunoia/web");
await eunoia.init();
layout = eunoia.euler({ sets: { A: 5, B: 2, "A&B": 1 } });

@jolars/eunoia/svg is pure JavaScript (no WebAssembly), so it already works directly from a CDN with no init(). Full runnable examples (a Quarto document and a standalone HTML page) are in examples/.

Citation

If you use Eunoia in your research, please cite the paper:

Larsson, J., & Lee, N. M. (2026). Eunoia: Area-Proportional Euler and Venn Diagrams in Rust, Julia, Python, R, and JavaScript (arXiv:2611.02198). arXiv. https://doi.org/10.48550/arXiv.2611.02198

@misc{larsson2026f,
  title         = {Eunoia: {{Area}}-Proportional {{Euler}} and {{Venn}} Diagrams in {{Rust}}, {{Julia}}, {{Python}}, {{R}}, and {{JavaScript}}},
  shorttitle    = {Eunoia},
  author        = {Larsson, Johan and Lee, Nicole M.},
  year          = {2026},
  month         = nov,
  number        = {arXiv:2611.02198},
  eprint        = {2611.02198},
  primaryclass  = {stat.CO},
  publisher     = {arXiv},
  doi           = {10.48550/arXiv.2611.02198},
  archiveprefix = {arXiv}
}
BibLaTeX
@online{larsson2026f,
  title       = {Eunoia: {{Area}}-Proportional {{Euler}} and {{Venn}} Diagrams in {{Rust}}, {{Julia}}, {{Python}}, {{R}}, and {{JavaScript}}},
  shorttitle  = {Eunoia},
  author      = {Larsson, Johan and Lee, Nicole M.},
  date        = {2026-11-01},
  eprint      = {2611.02198},
  eprinttype  = {arXiv},
  eprintclass = {stat.CO},
  doi         = {10.48550/arXiv.2611.02198},
  pubstate    = {prepublished}
}

For reproducibility, also cite the software release you used. Select that release in the Zenodo archive and export its citation. The concept DOI 10.5281/zenodo.20665805 identifies Eunoia across all releases.

CITATION.cff contains the software metadata and preferred paper citation. The Eunoia citation page renders the paper in APA, BibTeX, BibLaTeX, and other formats.

License

Eunoia is distributed under the terms of either the MIT license or the Apache License 2.0, at your option.

About

A Rust library for Euler and Venn Diagrams

Topics

Resources

Contributing

Stars

16 stars

Watchers

1 watching

Forks

Releases

Sponsor this project

Used by

Contributors

Languages