[](https://crates.io/crates/space-filling)
[](https://docs.rs/space-filling)
Note: this is a subject of ongoing research, no stability guarantees are made.
You can read this paper for introduction:
[Paul Bourke - Random space filling of the plane (2011)](http://paulbourke.net/fractals/randomtile/).
However, the provided search algorithm for the next location is inefficient,
and offers very limited control over the distribution[[1]](#footnote_1).
In this work, I present two solvers for the following equation:
![](doc/eq1.svg)
**sdfn** are signed distance functions (primitives), by aggregate minima forming together a complex distance field - further denoted **"SDF"**.
The goal of algorithm lies in finding a safe domain, guaranteed to not intersect with any shapes.
A generic and parallel interface was implemented. Currently supported:
- User-defined distributions (including fractal and random)
- Any shapes which can be represented with SDF: curves, regular polygons, non-convex and disjoint areas, fractals or any sets with non-integer hausdorff dimension (as long as the distance can be approximated).
### Argmax2D
SDF is stored as a discrete bitmap, with memory layout reminiscent of z-order curve. Solver is guaranteed to always find **global maxima**, but increasing precision requires quadratic memory.
### GD-ADF
A paper "Adaptively Sampled Distance Fields" (doi:[10.1145/344779.344899](https://dl.acm.org/doi/10.1145/344779.344899)) offered an idea of reducing memory consumption, however it was very elaborate to not include _any_ hints for a practical implementation. The only one being - using polynomial approximations for every node of the k-d tree; however, current work takes a different path - by storing function primitives themselves in each node (bucket). Redundant primitive elimination within a bucket was performed using [interior-point method](https://en.wikipedia.org/wiki/Interior-point_method).
ADF itself implements SDF trait, allowing for complex fields composed of millions of primitives to be sampled efficiently — as opposed to computing it directly — with quadratic complexity in nature.
However, primitive elimination is not yet perfect. An elimination algorithm which is both precise and fast enough will be a subject of further theoretical research.
Once the representation is obtained, the role of optimizer takes place. For practical purposes, gradient descent with exponential convergence has been chosen — making GD-ADF a **local maxima** algorithm; as described by following equation:
![](doc/eq2.svg)
Since by definition, first order derivative of distance field is constant, only direction of the gradient is considered — eliminating a number of issues with both GD/IPM; and as a bonus, rendering them to be no longer dependent on the field magnitude directly.
Unlike Argmax2D, GD-ADF offers 10-100x memory reduction, as well as continuous, exact field representation. Various speed tradeoffs are provided, including both single and double float precision.
## Examples
You can run examples with following command:
`cargo run --release --features "drawing" --example `
You can add `-- -C target-cpu=native` at the command end to further improve the speed.
[`01_fractal_distribution`](examples/argmax2d/01_fractal_distribution.rs)
Each subsequent circle is inserted at the maxima of distance field.
![](doc/fractal_distribution.png)
[`02_random_distribution`](examples/gd_adf/02_random_distribution.rs)
Given `(xy, magnitude)` of the maxima, a new random circle is inserted within a domain of radius `magnitude` and center `xy`.
![](doc/random_distribution.png)
[`03_embedded`](examples/argmax2d/03_embedded.rs)
A distribution embedded in a distribution.
[`04_polymorphic`](examples/gd_adf/04_polymorphic.rs)
Showcasing:
- Dynamic dispatch interface;
- Random distribution of mixed shapes;
- Random color and texture fill style;
- Parallel generation and drawing.
[`05_image_dataset`](examples/argmax2d/05_image_dataset.rs)
Display over 100'000 images.
Run with `cargo run --release --features "drawing" --example image_dataset -- "" -C target-cpu=native`
![](doc/image_dataset.gif)
[`06_custom_primitive`](examples/gd_adf/06_custom_primitive.rs)
A user-defined primitive.
![](doc/custom_primitive.png)
## Past work
In `src/legacy` you can find numeruos algorithms which are worth re-exploring, including quadtree and GPU implementations.
## Future work
- [x] Add more sample SDFs, and generic draw trait
- [x] Extend to support precision below 2-16 (gigapixel resolution)
- [x] Rework traits
- [ ] Generalize to N dimensions
Once above are done, I will use this library for my next project "Gallery of Babel".
#### Footnotes
: J. Shier, "A Million-Circle Fractal": [https://www.d.umn.edu/~ddunham/circlepat.html](https://www.d.umn.edu/~ddunham/circlepat.html)
«...Run time was 14.7 hours.»