Sign Up for Free

RunKit +

Try any Node.js package right in your browser

This is a playground to test code. It runs a full Node.js environment and already has all of npm’s 400,000 packages pre-installed, including with all npm packages installed. Try it out:

var poisson = require("")

This service is provided by RunKit and is not affiliated with npm, Inc or the package authors. v1.0.7

nD Poisson-disc sampling w/ support for spatial density functions and custom PRNGs

npm version npm downloads Twitter Follow

This project is part of the monorepo.


example screenshot

nD Poisson disk sampling with support for variable spatial density, custom PRNGs (via's IRandom interface & implementations) and customizable quality settings.

Currently uses a k-D tree implementation to speed up the sampling process, but will be refactored to support other, alternative spatial indexing mechanisms...


STABLE - used in production

Related packages


yarn add

Package sizes (gzipped): ESM: 337 bytes / CJS: 391 bytes / UMD: 501 bytes


Usage examples

Several demos in this repo's /examples directory are using this package.

A selection:

ScreenshotDescriptionLive demoSource
Poisson-disk shape-aware sampling, Voronoi & Minimum Spanning Tree visualizationDemoSource


Generated API docs

The package provides a single function samplePoisson() and the following options to customize the sampling process:

interface PoissonOpts {
     * Point generator function. Responsible for producing a new
     * candidate point within user defined bounds using provided RNG.
    points: PointGenerator;
     * Density field function. Called for each new sample point created
     * by point generator and should return the exclusion radius for
     * given point location. If this option is given as number, uses
     * this value to create a uniform distance field.
    density: DensityFunction | number;
     * Spatial indexing implementation. Currently only KdTree from
     * package is supported and must be
     * pre-initialized to given dimensions. Furthermore, pre-seeding the
     * tree allows already indexed points to participate in the sampling
     * process and act as exclusion zones.
    accel: KdTree<ReadonlyVec, any>;
     * Max number of samples to produce.
    max: number;
     * Step distance for the random walk each failed candidate point is
     * undergoing. This distance should be adjusted depending on overall
     * sampling area/bounds. Default: 1
    jitter?: number;
     * Number of random walk steps performed before giving up on a
     * candidate point. Default: 5
    iter?: number;
     * Number of allowed failed continuous candidate points before
     * stopping entire sampling process. Increasing this value improves
     * overall quality, especially in dense regions with small radii.
     * Default: 500
    quality?: number;
     * Random number generator instance. Default
     * (aka Math.random)
    rnd?: IRandom;

example output

import { samplePoisson } from "";

import { asSvg, svgDoc, circle } from "";
import { KdTree } from "";
import { fit01 } from "";
import { dist2, randMinMax2 } from "";

accel = new KdTree(2);

pts = samplePoisson({
    points: () => randMinMax2(null, [0, 0], [500, 500]),
    density: (p) => fit01(Math.pow(Math.max(dist2(p, [250, 250]) / 250, 0), 2), 2, 10),
    iter: 5,
    max: 8000,
    quality: 500

// use to visualize results
// each circle's radius is set to distance to its nearest neighbor
circles = => circle(p, dist2(p, accel.selectKeys(p, 2, 40)[1]) / 2));

document.body.innerHTML = asSvg(svgDoc({ fill: "none", stroke: "red" }, ...circles));


Karsten Schmidt


© 2016 - 2020 Karsten Schmidt // Apache Software License 2.0

RunKit is a free, in-browser JavaScript dev environment for prototyping Node.js code, with every npm package installed. Sign up to share your code.
Sign Up for Free