Crate fast_poisson[][src]

Generate a Poisson disk distribution.

This is an implementation of Bridson’s “Fast Poisson Disk Sampling” algorithm in arbitrary dimensions.

  • Iterator-based generation lets you leverage the full power of Rust’s Iterators
  • Lazy evaluation of the distribution means that even complex Iterator chains are as fast as O(N); with other libraries operations like mapping into another struct become O(N²) or more!
  • Using Rust’s const generics allows you to consume the distribution with no additional dependencies

Features

These are the optional features you can enable in your Cargo.toml:

  • single_precision changes the output, and all of the internal calculations, from using double-precision f64 to single-precision f32. Distributions generated with the single-precision feature are not required nor expected to match those generated without it.
  • small_rng changes the internal PRNG used to generate the distribution: By default Xoshiro256StarStar is used, but with this feature enabled then Xoshiro128StarStar is used instead. This reduces the memory used for the PRNG’s state from 256 bits to 128 bits, and may be more performant for 32-bit systems.
  • derive_serde automatically derives Serde’s Serialize and Deserialize traits for Poisson, This relies on the serde_arrays crate to allow (de)serializing the const generic arrays used by Poisson.

Requirements

This library requires Rust 1.51.0 or later, as it relies on const generics to return fixed-length points (e.g. [x, y] or [x, y, z]) without adding additional external dependencies to your code.

Examples

use fast_poisson::Poisson2D;

// Easily generate a simple `Vec`
let points: Vec<[f64; 2]> = Poisson2D::new().generate();

// To fill a box, specify the width and height:
let points = Poisson2D::new().with_dimensions([100.0, 100.0], 5.0);

// Leverage `Iterator::map` to quickly and easily convert into a custom type in O(N) time!
// Also see the `Poisson::to_vec()` method
struct Point {
    x: f64,
    y: f64,
}
let points = Poisson2D::new().iter().map(|[x, y]| Point { x, y });

// Distributions are lazily evaluated; here only 5 points will be calculated!
let points = Poisson2D::new().iter().take(5);

// `Poisson` can be directly consumed in for loops:
for point in Poisson2D::new() {
    println!("X: {}; Y: {}", point[0], point[1]);
}

Higher-order Poisson disk distributions are generated just as easily:

use fast_poisson::{Poisson, Poisson3D, Poisson4D};

// 3-dimensional distribution
let points_3d = Poisson3D::new().iter();

// 4-dimensional distribution
let mut points_4d = Poisson4D::new();
// To achieve desired levels of performance, you should set a larger radius for higher-order
// distributions
points_4d.with_dimensions([1.0; 4], 0.2);
let points_4d = points_4d.iter();

// For more than 4 dimensions, use `Poisson` directly:
let mut points_7d = Poisson::<7>::new();
points_7d.with_dimensions([1.0; 7], 0.6);
let points_7d = points_7d.iter();

Upgrading

0.4.x

This version is 100% backwards-compatible with 0.3.x and 0.2.0, however fast_poisson has been relicensed as of this version.

Several bugs were identified and fixed in the underlying algorithms; as a result, distributions generated with 0.4.0 will not match those generated in earlier versions.

0.3.x

This version adds no breaking changes and is backwards-compatible with 0.2.0.

0.2.0

This version adds some breaking changes:

2 dimensions no longer assumed

In version 0.1.0 you could directly instantiate Poisson and get a 2-dimensional distribution. Now you must specifiy that you want 2 dimensions using either Poisson<2> or Poisson2D.

Returned points are arrays

In version 0.1.0 the distribution was returned as an iterator over (f64, f64) tuples representing each point. To leverage Rust’s new const generics feature and support arbitrary dimensions, the N-dimensional points are now [f64; N] arrays.

Builder pattern

Use the build pattern to instantiate new distributions. This will not work:

let poisson = Poisson2D {
    width: 100.0,
    height: 100.0,
    radius: 5.0,
    ..Default::default()
};
let points = poisson.iter();

Instead, leverage the new builder methods:

let mut poisson = Poisson2D::new();
poisson.with_dimensions([100.0; 2], 5.0);
let points = poisson.iter();

This change frees me to make additional changes to how internal state is stored without necessarily requiring additional changes to the API.

Structs

Iter

An iterator over the points in the Poisson disk distribution

Poisson

Poisson disk distribution in N dimensions

Type Definitions

Point

A Point is simply an array of Float values

Poisson2D

Poisson disk distribution in 2 dimensions

Poisson3D

Poisson disk distribution in 3 dimensions

Poisson4D

Poisson disk distribution in 4 dimensions