-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Prepare version 0.2.0 branch * Updated 1-dimensional examples * Added 2-dimensional euclidean API * Added 2-dimensional toroidal API * Updated README.md
- Loading branch information
Iker Ruiz de Infante Gonzalez
authored
Jun 17, 2023
1 parent
fbba649
commit 02f4a12
Showing
75 changed files
with
1,240 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
# 2-dimensional euclidean grid example | ||
|
||
Let's see how to use the wfc4j library to generate a planar pattern. These are the tiles we have available: | ||
|
||
| NE | NW | SE | SW | | ||
|:---:|:---:|:---:|:---:| | ||
|<img src="../assets/2-dimensional-euclidean/NE.png">|<img src="../assets/2-dimensional-euclidean/NW.png">|<img src="../assets/2-dimensional-euclidean/SE.png">|<img src="../assets/2-dimensional-euclidean/SW.png">| | ||
|
||
```java | ||
import java.util.HashSet; | ||
import eu.irzinfante.wfc4j.model.Tile; | ||
|
||
Tile<String> NE = new Tile<>("NE"), NW = new Tile<>("NW"), SE = new Tile<>("SE"), SW = new Tile<>("SW"); | ||
|
||
var tileSet = new HashSet<Tile<String>>(); | ||
tileSet.add(NE); tileSet.add(NW); tileSet.add(SE); tileSet.add(SW); | ||
``` | ||
|
||
So, the logical adjacencies between tiles are the following: | ||
|
||
|
||
| Tile | Left adjacent tiles | Right adjacent tiles | Bottom adjacent tiles | Top adjacent tiles | | ||
|:----:|:---------------------:|:----------------------:|:----------------------:|:----------------------:| | ||
|<img src="../assets/2-dimensional-euclidean/NE.png">|<img src="../assets/2-dimensional-euclidean/NW.png"> $~~~~$ <img src="../assets/2-dimensional-euclidean/SW.png">|<img src="../assets/2-dimensional-euclidean/NW.png"> $~~~~$ <img src="../assets/2-dimensional-euclidean/SW.png">|<img src="../assets/2-dimensional-euclidean/SE.png"> $~~~~$ <img src="../assets/2-dimensional-euclidean/SW.png">|<img src="../assets/2-dimensional-euclidean/SE.png"> $~~~~$ <img src="../assets/2-dimensional-euclidean/SW.png">| | ||
|<img src="../assets/2-dimensional-euclidean/NW.png">|<img src="../assets/2-dimensional-euclidean/NE.png"> $~~~~$ <img src="../assets/2-dimensional-euclidean/SE.png">|<img src="../assets/2-dimensional-euclidean/NE.png"> $~~~~$ <img src="../assets/2-dimensional-euclidean/SE.png">|<img src="../assets/2-dimensional-euclidean/SE.png"> $~~~~$ <img src="../assets/2-dimensional-euclidean/SW.png">|<img src="../assets/2-dimensional-euclidean/SE.png"> $~~~~$ <img src="../assets/2-dimensional-euclidean/SW.png">| | ||
|<img src="../assets/2-dimensional-euclidean/SE.png">|<img src="../assets/2-dimensional-euclidean/NW.png"> $~~~~$ <img src="../assets/2-dimensional-euclidean/SW.png">|<img src="../assets/2-dimensional-euclidean/NW.png"> $~~~~$ <img src="../assets/2-dimensional-euclidean/SW.png">|<img src="../assets/2-dimensional-euclidean/NE.png"> $~~~~$ <img src="../assets/2-dimensional-euclidean/NW.png">|<img src="../assets/2-dimensional-euclidean/NE.png"> $~~~~$ <img src="../assets/2-dimensional-euclidean/NW.png">| | ||
|<img src="../assets/2-dimensional-euclidean/SW.png">|<img src="../assets/2-dimensional-euclidean/NE.png"> $~~~~$ <img src="../assets/2-dimensional-euclidean/SE.png">|<img src="../assets/2-dimensional-euclidean/NE.png"> $~~~~$ <img src="../assets/2-dimensional-euclidean/SE.png">|<img src="../assets/2-dimensional-euclidean/NE.png"> $~~~~$ <img src="../assets/2-dimensional-euclidean/NW.png">|<img src="../assets/2-dimensional-euclidean/NE.png"> $~~~~$ <img src="../assets/2-dimensional-euclidean/NW.png">| | ||
|
||
```java | ||
import eu.irzinfante.wfc4j.model.TileMap2D; | ||
import eu.irzinfante.wfc4j.enums.Side2D; | ||
|
||
var adjacentNWSW = new HashSet<Tile<String>>(); | ||
adjacentNWSW.add(NW); adjacentNWSW.add(SW); | ||
|
||
var adjacentSESW = new HashSet<Tile<String>>(); | ||
adjacentSESW.add(SE); adjacentSESW.add(SW); | ||
|
||
var adjacentNESE = new HashSet<Tile<String>>(); | ||
adjacentNESE.add(NE); adjacentNESE.add(SE); | ||
|
||
var adjacentNENW = new HashSet<Tile<String>>(); | ||
adjacentNENW.add(NE); adjacentNENW.add(NW); | ||
|
||
var tileMap = new TileMap2D<>(tileSet); | ||
|
||
tileMap.setAdjacents(NE, Side2D.Left, adjacentNWSW); tileMap.setAdjacents(NE, Side2D.Right, adjacentNWSW); | ||
tileMap.setAdjacents(NE, Side2D.Bottom, adjacentSESW); tileMap.setAdjacents(NE, Side2D.Top, adjacentSESW); | ||
|
||
tileMap.setAdjacents(NW, Side2D.Left, adjacentNESE); tileMap.setAdjacents(NW, Side2D.Right, adjacentNESE); | ||
tileMap.setAdjacents(NW, Side2D.Bottom, adjacentSESW); tileMap.setAdjacents(NW, Side2D.Top, adjacentSESW); | ||
|
||
tileMap.setAdjacents(SE, Side2D.Left, adjacentNWSW); tileMap.setAdjacents(SE, Side2D.Right, adjacentNWSW); | ||
tileMap.setAdjacents(SE, Side2D.Bottom, adjacentNENW); tileMap.setAdjacents(SE, Side2D.Top, adjacentNENW); | ||
|
||
tileMap.setAdjacents(SW, Side2D.Left, adjacentNESE); tileMap.setAdjacents(SW, Side2D.Right, adjacentNESE); | ||
tileMap.setAdjacents(SW, Side2D.Bottom, adjacentNENW); tileMap.setAdjacents(SW, Side2D.Top, adjacentNENW); | ||
``` | ||
|
||
Now we can instantiate the API class with an 8 by 6 grid: | ||
|
||
```java | ||
import eu.irzinfante.wfc4j.api.WaveFunctionCollapseEuclidean2D; | ||
|
||
int gridSizeX = 8, gridSizeY = 6; | ||
var WFC = new WaveFunctionCollapseEuclidean2D<String>(tileMap, gridSizeX, gridSizeY, 148576907989080L); | ||
``` | ||
|
||
We will perform 2 executions of the `generate` function in order: | ||
|
||
- For the first one we won't impose any restriction: | ||
|
||
```java | ||
import eu.irzinfante.wfc4j.util.WFCUtils; | ||
|
||
WFC.clear(); | ||
var result = WFC.generate(); | ||
|
||
System.out.println(WFCUtils.WFC2DToString(result)); | ||
``` | ||
|
||
<img src="../assets/2-dimensional-euclidean/result1.png"> | ||
|
||
- For the second one we will impose some constraint on the center of the grid: | ||
|
||
```java | ||
import java.util.Arrays; | ||
import eu.irzinfante.wfc4j.model.Cell2D; | ||
|
||
WFC.clear(); | ||
WFC.setCellConstraint(new Cell2D<>(new HashSet<>(Arrays.asList(SE)), 4, 3)); | ||
WFC.setCellConstraint(new Cell2D<>(new HashSet<>(Arrays.asList(NW)), 5, 4)); | ||
result = WFC.generate(); | ||
|
||
System.out.println(WFCUtils.WFC2DToString(result)); | ||
``` | ||
|
||
<img src="../assets/2-dimensional-euclidean/result2.png"> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
# 2-dimensional toroidal grid example | ||
|
||
In this example we will see how to use the wfc4j library to generate a 2D toroidal pattern with programmatically constructed tiles. Each tile will be the combination of two components. | ||
|
||
- First component: | ||
|
||
| LR__ | LB__ | LT__ | RB__ | RT__ | BT__ | | ||
|:----:|:----:|:----:|:----:|:----:|:----:| | ||
|<img src="../assets/2-dimensional-toroidal/LR__.png">|<img src="../assets/2-dimensional-toroidal/LB__.png">|<img src="../assets/2-dimensional-toroidal/LT__.png">|<img src="../assets/2-dimensional-toroidal/RB__.png">|<img src="../assets/2-dimensional-toroidal/RT__.png">|<img src="../assets/2-dimensional-toroidal/BT__.png">| | ||
|
||
- Second component: | ||
|
||
| __LR | __LB | __LT | __RB | __RT | __BT | | ||
|:----:|:----:|:----:|:----:|:----:|:----:| | ||
|<img src="../assets/2-dimensional-toroidal/__LR.png">|<img src="../assets/2-dimensional-toroidal/__LB.png">|<img src="../assets/2-dimensional-toroidal/__LT.png">|<img src="../assets/2-dimensional-toroidal/__RB.png">|<img src="../assets/2-dimensional-toroidal/__RT.png">|<img src="../assets/2-dimensional-toroidal/__BT.png">| | ||
|
||
And therefore the adjacency of the tiles will be based on how the two components of each tile fit together with the components of the adjacent tiles. In our example this is computed like this: | ||
|
||
```java | ||
import eu.irzinfante.wfc4j.enums.Side2D; | ||
import eu.irzinfante.wfc4j.exceptions.DimensionException; | ||
import eu.irzinfante.wfc4j.exceptions.TileException; | ||
import eu.irzinfante.wfc4j.model.Tile; | ||
import eu.irzinfante.wfc4j.model.TileMap2D; | ||
|
||
final String LR = "LR", LB = "LB", LT = "LT", RB = "RB", RT = "RT", BT = "BT"; | ||
final var components = new String[] {LR, LB, LT, RB, RT, BT}; | ||
|
||
var tileSet = new HashSet<Tile<String>>(); | ||
for(var first : components) { | ||
for(var second : components) { | ||
tileSet.add(new Tile<>(first + second)); | ||
} | ||
} | ||
|
||
var tileMap = new TileMap2D<>(tileSet); | ||
|
||
for(var tile : tileSet) { | ||
var tileFirstLeft = tile.getValue().substring(0, 2).contains("L"); | ||
var tileSecondLeft = tile.getValue().substring(2, 4).contains("L"); | ||
var leftAdjacents = new HashSet<Tile<String>>(); | ||
|
||
var tileFirstRight = tile.getValue().substring(0, 2).contains("R"); | ||
var tileSecondRight = tile.getValue().substring(2, 4).contains("R"); | ||
var rightAdjacents = new HashSet<Tile<String>>(); | ||
|
||
var tileFirstBottom = tile.getValue().substring(0, 2).contains("B"); | ||
var tileSecondBottom = tile.getValue().substring(2, 4).contains("B"); | ||
var bottomAdjacents = new HashSet<Tile<String>>(); | ||
|
||
var tileFirstTop = tile.getValue().substring(0, 2).contains("T"); | ||
var tileSecondTop = tile.getValue().substring(2, 4).contains("T"); | ||
var topAdjacents = new HashSet<Tile<String>>(); | ||
|
||
for(var adjacent : tileSet) { | ||
var adjacentFirstLeft = adjacent.getValue().substring(0, 2).contains("L"); | ||
var adjacentSecondLeft = adjacent.getValue().substring(2, 4).contains("L"); | ||
if( (tileFirstRight && adjacentFirstLeft && tileSecondRight && adjacentSecondLeft) || | ||
(tileFirstRight && adjacentFirstLeft && !tileSecondRight && !adjacentSecondLeft) || | ||
(!tileFirstRight && !adjacentFirstLeft && tileSecondRight && adjacentSecondLeft) || | ||
(!tileFirstRight && !adjacentFirstLeft && !tileSecondRight && !adjacentSecondLeft) | ||
) { | ||
rightAdjacents.add(adjacent); | ||
} | ||
|
||
var adjacentFirstRight = adjacent.getValue().substring(0, 2).contains("R"); | ||
var adjacentSecondRight = adjacent.getValue().substring(2, 4).contains("R"); | ||
if( (tileFirstLeft && adjacentFirstRight && tileSecondLeft && adjacentSecondRight) || | ||
(tileFirstLeft && adjacentFirstRight && !tileSecondLeft && !adjacentSecondRight) || | ||
(!tileFirstLeft && !adjacentFirstRight && tileSecondLeft && adjacentSecondRight) || | ||
(!tileFirstLeft && !adjacentFirstRight && !tileSecondLeft && !adjacentSecondRight) | ||
) { | ||
leftAdjacents.add(adjacent); | ||
} | ||
|
||
var adjacentFirstTop = adjacent.getValue().substring(0, 2).contains("T"); | ||
var adjacentSecondTop = adjacent.getValue().substring(2, 4).contains("T"); | ||
if( (tileFirstBottom && adjacentFirstTop && tileSecondBottom && adjacentSecondTop) || | ||
(tileFirstBottom && adjacentFirstTop && !tileSecondBottom && !adjacentSecondTop) || | ||
(!tileFirstBottom && !adjacentFirstTop && tileSecondBottom && adjacentSecondTop) || | ||
(!tileFirstBottom && !adjacentFirstTop && !tileSecondBottom && !adjacentSecondTop) | ||
) { | ||
bottomAdjacents.add(adjacent); | ||
} | ||
|
||
var adjacentFirstBottom = adjacent.getValue().substring(0, 2).contains("B"); | ||
var adjacentSecondBottom = adjacent.getValue().substring(2, 4).contains("B"); | ||
if( (tileFirstTop && adjacentFirstBottom && tileSecondTop && adjacentSecondBottom) || | ||
(tileFirstTop && adjacentFirstBottom && !tileSecondTop && !adjacentSecondBottom) || | ||
(!tileFirstTop && !adjacentFirstBottom && tileSecondTop && adjacentSecondBottom) || | ||
(!tileFirstTop && !adjacentFirstBottom && !tileSecondTop && !adjacentSecondBottom) | ||
) { | ||
topAdjacents.add(adjacent); | ||
} | ||
} | ||
|
||
tileMap.setAdjacents(tile, Side2D.Left, leftAdjacents); | ||
tileMap.setAdjacents(tile, Side2D.Right, rightAdjacents); | ||
tileMap.setAdjacents(tile, Side2D.Bottom, bottomAdjacents); | ||
tileMap.setAdjacents(tile, Side2D.Top, topAdjacents); | ||
} | ||
``` | ||
|
||
> Please, take your time on understanding the code above. | ||
Now we can instantiate the API class with an 6 by 6 grid: | ||
|
||
```java | ||
import eu.irzinfante.wfc4j.api.WaveFunctionCollapseToroidal2D; | ||
|
||
int gridSizeX = 6, gridSizeY = 6; | ||
var WFC = new WaveFunctionCollapseToroidal2D<String>(tileMap, gridSizeX, gridSizeY, 103478937644546L); | ||
``` | ||
|
||
Finally we will perform the excution of the `generate` function: | ||
|
||
```java | ||
import eu.irzinfante.wfc4j.util.WFCUtils; | ||
|
||
var result = WFC.generate(); | ||
System.out.println(WFCUtils.WFC2DToString(result)); | ||
``` | ||
|
||
<img src="../assets/2-dimensional-toroidal/result.png"> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.