Skip to content

Commit

Permalink
improve documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
guo-yong-zhi committed Jun 3, 2023
1 parent 1834c04 commit 56af8c2
Showing 1 changed file with 12 additions and 7 deletions.
19 changes: 12 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
# Stuffing
# Stuffing.jl
[![CI](https://github.com/guo-yong-zhi/Stuffing.jl/actions/workflows/ci.yml/badge.svg)](https://github.com/guo-yong-zhi/Stuffing.jl/actions/workflows/ci.yml) [![CI-nightly](https://github.com/guo-yong-zhi/Stuffing.jl/actions/workflows/ci-nightly.yml/badge.svg)](https://github.com/guo-yong-zhi/Stuffing.jl/actions/workflows/ci-nightly.yml) [![codecov](https://codecov.io/gh/guo-yong-zhi/Stuffing.jl/branch/main/graph/badge.svg?token=43TOrL25V7)](https://codecov.io/gh/guo-yong-zhi/Stuffing.jl) [![DOI](https://zenodo.org/badge/349631351.svg)](https://zenodo.org/badge/latestdoi/349631351)
This's an algorithm for solving **2D irregular nesting problems** (also known as cutting problems or packing problems).
The algorithm accepts arbitrary **binary or ternary raster masks** as inputs and is good at handling the nesting problems of many gadgets. The implementation is based on quadtree & gradient optimization. Also, it can be parallelized if you start `julia` with `julia --threads k`. This package is used by [WordCloud.jl](https://github.com/guo-yong-zhi/WordCloud.jl).
This algorithm provides a solution for **2D irregular nesting problems** (also known as cutting problems or packing problems). It is capable of processing arbitrary shapes represented by **binary or ternary raster masks** as inputs and excels in efficiently handling the nesting problems associated with numerous small objects. The implementation of this algorithm is based on quadtree and gradient optimization techniques. Additionally, it can be parallelized by launching `julia` with `julia --threads k`. This package is utilized by [WordCloud.jl](https://github.com/guo-yong-zhi/WordCloud.jl).
Examples: [collision detection](./examples/collision.jl), [dynamic collision detection](./examples/dynamiccollisions.jl), [packing](./examples/packing.jl)
Benchmark: [collision benchmark](./examples/collision_benchmark.jl), [fit benchmark](https://github.com/guo-yong-zhi/WordCloud/blob/master/examples/benchmark.jl)
Benchmark: [collision benchmark](./examples/collision_benchmark.jl), [fit benchmark](https://github.com/guo-yong-zhi/WordCloud.jl/blob/master/examples/benchmark.jl)
***
```
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
Expand Down Expand Up @@ -46,10 +45,16 @@ Benchmark: [collision benchmark](./examples/collision_benchmark.jl), [fit benchm
import Pkg; Pkg.add("Stuffing")
```
# Algorithm Description
* First, a **ternary raster pyramid** (implemented as [`AbstractStackedQTree`](./src/qtrees.jl)) is built for every original binary raster mask. It consists of downsampled layers of the original mask. Each successive layer is downsampled at a scale of 2:1. In this way, the pyramid can also be seen as a set of hierarchical bounding boxes. The value of each pixel of each layer (the node of the tree) can be `FULL`, `EMPTY` or `MIX`.
The algorithm consists of three main steps:
1. **Ternary Raster Pyramid Construction**: Initially, a ternary raster pyramid ([`AbstractStackedQTree`](./src/qtrees.jl)) is created for each original binary raster mask. This pyramid comprises downsampled layers of the original mask. Each subsequent layer is downsampled at a 2:1 scale. Consequently, the pyramid can be viewed as a collection of hierarchical bounding boxes. Each pixel in every layer (tree node) can take one of three values: `FULL`, `EMPTY`, or `MIX`.

![pyramid1](./res/pyramid1.png)
![pyramid2](./res/pyramid2.png)
* Second, a **top-down method** ([`collision`](./src/qtree_functions.jl)) is used to detect collision between two pyramids (trees). On the level 𝑙 and coordinates (𝑎,𝑏), if one tree's node is `FULL` and the other's is NOT `EMPTY`, then these two trees collide at (𝑙,𝑎,𝑏). However, to detect collisions between many objects, pairwise detection would be time-consuming. So, we first locate the objects in hierarchical sub-regions (implemented as a [`HashSpacialQTree` or `LinkedSpacialQTree`](./src/qtree.jl)), and then detect the collision between objects within each sub-region and between the objects in the sub-regions and those in their ancestral regions (see [`totalcollisions_spacial`, `partialcollisions` and `locate!`](./src/qtree_functions.jl)).

2. **Top-Down Collision Detection**: The algorithm employs a top-down approach ([`collision`](./src/qtree_functions.jl)) to identify collisions between two pyramids or trees. At level 𝑙 and coordinates (𝑎,𝑏), if a node in one tree is `FULL` and the corresponding node in the other tree is not `EMPTY`, a collision occurs at (𝑙,𝑎,𝑏). However, pairwise collision detection between multiple objects would be time-consuming. To address this, the algorithm first locates the objects within hierarchical sub-regions ([`HashSpacialQTree` or `LinkedSpacialQTree`](./src/qtree.jl)). It then detects collisions between objects within each sub-region and between objects in sub-regions and their ancestral regions ([`totalcollisions_spacial`, `partialcollisions` and `locate!`](./src/qtree_functions.jl)).

![collision](./res/collision.png)
* At last, each object in collision pair is moved according to the **local gradient** (calculated by [`grad2d`](./src/fit.jl)) near the collision point (𝑙,𝑎,𝑏), that is, moving the object away from `EMPTY` region. This will enlarge space between them. After moving the objects, the `AbstractStackedQTree`s should be rebuilt for the next round of collision detection.

3. **Object Movement and Reconstruction**: In the final step, each object in a collision pair is moved based on the local gradient ([`grad2d`](./src/fit.jl)) near the collision point (𝑙,𝑎,𝑏). The movement aims to separate the objects and create more space between them. Specifically, the objects are shifted away from the `EMPTY` regions. After moving the objects, the algorithm rebuilds the `AbstractStackedQTree`s to prepare for the next round of collision detection.

![gradient](./res/gradient.png)

2 comments on commit 56af8c2

@guo-yong-zhi
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JuliaRegistrator register()

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Registration pull request updated: JuliaRegistries/General/84813

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via:

git tag -a v0.9.0 -m "<description of version>" 56af8c27a5885382aa9d4acf7763edd5808a24d3
git push origin v0.9.0

Please sign in to comment.