unsigned to uint32_t conversion for the wfc module.

This commit is contained in:
Relintai 2022-04-21 16:43:04 +02:00
parent 531dc783d8
commit ec6b52f5d8
9 changed files with 146 additions and 147 deletions

View File

@ -4,7 +4,7 @@
constexpr int directions_x[4] = { 0, -1, 1, 0 };
constexpr int directions_y[4] = { -1, 0, 0, 1 };
constexpr unsigned get_opposite_direction(unsigned direction) {
constexpr uint32_t get_opposite_direction(uint32_t direction) {
return 3 - direction;
}

View File

@ -11,19 +11,19 @@
struct OverlappingWFCOptions {
bool periodic_input; // True if the input is toric.
bool periodic_output; // True if the output is toric.
unsigned out_height; // The height of the output in pixels.
unsigned out_width; // The width of the output in pixels.
unsigned symmetry; // The number of symmetries (the order is defined in wfc).
uint32_t out_height; // The height of the output in pixels.
uint32_t out_width; // The width of the output in pixels.
uint32_t symmetry; // The number of symmetries (the order is defined in wfc).
bool ground; // True if the ground needs to be set (see init_ground).
unsigned pattern_size; // The width and height in pixel of the patterns.
uint32_t pattern_size; // The width and height in pixel of the patterns.
//Get the wave height given these options.
unsigned get_wave_height() const {
uint32_t get_wave_height() const {
return periodic_output ? out_height : out_height - pattern_size + 1;
}
//Get the wave width given these options.
unsigned get_wave_width() const {
uint32_t get_wave_width() const {
return periodic_output ? out_width : out_width - pattern_size + 1;
}
};
@ -43,7 +43,7 @@ private:
const Array2D<T> &input, const OverlappingWFCOptions &options,
const int &seed,
const std::pair<Vector<Array2D<T>>, Vector<double>> &patterns,
const Vector<std::array<Vector<unsigned>, 4>> &propagator) :
const Vector<std::array<Vector<uint32_t>, 4>> &propagator) :
input(input), options(options), patterns(patterns.first), wfc(options.periodic_output, seed, patterns.second, propagator, options.get_wave_height(), options.get_wave_width()) {
// If necessary, the ground is set.
if (options.ground) {
@ -59,14 +59,14 @@ private:
generate_compatible(patterns.first)) {}
void init_ground(WFC &wfc, const Array2D<T> &input, const Vector<Array2D<T>> &patterns, const OverlappingWFCOptions &options) {
unsigned ground_pattern_id = get_ground_pattern_id(input, patterns, options);
uint32_t ground_pattern_id = get_ground_pattern_id(input, patterns, options);
for (unsigned j = 0; j < options.get_wave_width(); j++) {
for (uint32_t j = 0; j < options.get_wave_width(); j++) {
set_pattern(ground_pattern_id, options.get_wave_height() - 1, j);
}
for (unsigned i = 0; i < options.get_wave_height() - 1; i++) {
for (unsigned j = 0; j < options.get_wave_width(); j++) {
for (uint32_t i = 0; i < options.get_wave_height() - 1; i++) {
for (uint32_t j = 0; j < options.get_wave_width(); j++) {
wfc.remove_wave_pattern(i, j, ground_pattern_id);
}
}
@ -74,12 +74,12 @@ private:
wfc.propagate();
}
static unsigned get_ground_pattern_id(const Array2D<T> &input, const Vector<Array2D<T>> &patterns, const OverlappingWFCOptions &options) {
static uint32_t get_ground_pattern_id(const Array2D<T> &input, const Vector<Array2D<T>> &patterns, const OverlappingWFCOptions &options) {
// Get the pattern.
Array2D<T> ground_pattern = input.get_sub_array(input.height - 1, input.width / 2, options.pattern_size, options.pattern_size);
// Retrieve the id of the pattern.
for (unsigned i = 0; i < patterns.size(); i++) {
for (uint32_t i = 0; i < patterns.size(); i++) {
if (ground_pattern == patterns[i]) {
return i;
}
@ -92,7 +92,7 @@ private:
//Return the list of patterns, as well as their probabilities of apparition.
static std::pair<Vector<Array2D<T>>, Vector<double>> get_patterns(const Array2D<T> &input, const OverlappingWFCOptions &options) {
std::unordered_map<Array2D<T>, unsigned> patterns_id;
std::unordered_map<Array2D<T>, uint32_t> patterns_id;
Vector<Array2D<T>> patterns;
// The number of time a pattern is seen in the input image.
@ -100,15 +100,15 @@ private:
Vector<Array2D<T>> symmetries(
8, Array2D<T>(options.pattern_size, options.pattern_size));
unsigned max_i = options.periodic_input
uint32_t max_i = options.periodic_input
? input.height
: input.height - options.pattern_size + 1;
unsigned max_j = options.periodic_input
uint32_t max_j = options.periodic_input
? input.width
: input.width - options.pattern_size + 1;
for (unsigned i = 0; i < max_i; i++) {
for (unsigned j = 0; j < max_j; j++) {
for (uint32_t i = 0; i < max_i; i++) {
for (uint32_t j = 0; j < max_j; j++) {
// Compute the symmetries of every pattern in the image.
symmetries[0].data =
input
@ -124,7 +124,7 @@ private:
// The number of symmetries in the option class define which symetries
// will be used.
for (unsigned k = 0; k < options.symmetry; k++) {
for (uint32_t k = 0; k < options.symmetry; k++) {
auto res = patterns_id.insert(
std::make_pair(symmetries[k], patterns.size()));
@ -145,14 +145,14 @@ private:
//Return true if the pattern1 is compatible with pattern2 when pattern2 is at a distance (dy,dx) from pattern1.
static bool agrees(const Array2D<T> &pattern1, const Array2D<T> &pattern2, int dy, int dx) {
unsigned xmin = dx < 0 ? 0 : dx;
unsigned xmax = dx < 0 ? dx + pattern2.width : pattern1.width;
unsigned ymin = dy < 0 ? 0 : dy;
unsigned ymax = dy < 0 ? dy + pattern2.height : pattern1.width;
uint32_t xmin = dx < 0 ? 0 : dx;
uint32_t xmax = dx < 0 ? dx + pattern2.width : pattern1.width;
uint32_t ymin = dy < 0 ? 0 : dy;
uint32_t ymax = dy < 0 ? dy + pattern2.height : pattern1.width;
// Iterate on every pixel contained in the intersection of the two pattern.
for (unsigned y = ymin; y < ymax; y++) {
for (unsigned x = xmin; x < xmax; x++) {
for (uint32_t y = ymin; y < ymax; y++) {
for (uint32_t x = xmin; x < xmax; x++) {
// Check if the color is the same in the two patterns in that pixel.
if (pattern1.get(y, x) != pattern2.get(y - dy, x - dx)) {
return false;
@ -166,13 +166,13 @@ private:
// If agrees(pattern1, pattern2, dy, dx), then compatible[pattern1][direction]
// contains pattern2, where direction is the direction defined by (dy, dx)
// (see direction.hpp).
static Vector<std::array<Vector<unsigned>, 4>> generate_compatible(const Vector<Array2D<T>> &patterns) {
Vector<std::array<Vector<unsigned>, 4>> compatible = Vector<std::array<Vector<unsigned>, 4>>(patterns.size());
static Vector<std::array<Vector<uint32_t>, 4>> generate_compatible(const Vector<Array2D<T>> &patterns) {
Vector<std::array<Vector<uint32_t>, 4>> compatible = Vector<std::array<Vector<uint32_t>, 4>>(patterns.size());
// Iterate on every dy, dx, pattern1 and pattern2
for (unsigned pattern1 = 0; pattern1 < patterns.size(); pattern1++) {
for (unsigned direction = 0; direction < 4; direction++) {
for (unsigned pattern2 = 0; pattern2 < patterns.size(); pattern2++) {
for (uint32_t pattern1 = 0; pattern1 < patterns.size(); pattern1++) {
for (uint32_t direction = 0; direction < 4; direction++) {
for (uint32_t pattern2 = 0; pattern2 < patterns.size(); pattern2++) {
if (agrees(patterns[pattern1], patterns[pattern2], directions_y[direction], directions_x[direction])) {
compatible[pattern1][direction].push_back(pattern2);
}
@ -184,32 +184,32 @@ private:
}
// Transform a 2D array containing the patterns id to a 2D array containing the pixels.
Array2D<T> to_image(const Array2D<unsigned> &output_patterns) const {
Array2D<T> to_image(const Array2D<uint32_t> &output_patterns) const {
Array2D<T> output = Array2D<T>(options.out_height, options.out_width);
if (options.periodic_output) {
for (unsigned y = 0; y < options.get_wave_height(); y++) {
for (unsigned x = 0; x < options.get_wave_width(); x++) {
for (uint32_t y = 0; y < options.get_wave_height(); y++) {
for (uint32_t x = 0; x < options.get_wave_width(); x++) {
output.get(y, x) = patterns[output_patterns.get(y, x)].get(0, 0);
}
}
} else {
for (unsigned y = 0; y < options.get_wave_height(); y++) {
for (unsigned x = 0; x < options.get_wave_width(); x++) {
for (uint32_t y = 0; y < options.get_wave_height(); y++) {
for (uint32_t x = 0; x < options.get_wave_width(); x++) {
output.get(y, x) = patterns[output_patterns.get(y, x)].get(0, 0);
}
}
for (unsigned y = 0; y < options.get_wave_height(); y++) {
for (uint32_t y = 0; y < options.get_wave_height(); y++) {
const Array2D<T> &pattern = patterns[output_patterns.get(y, options.get_wave_width() - 1)];
for (unsigned dx = 1; dx < options.pattern_size; dx++) {
for (uint32_t dx = 1; dx < options.pattern_size; dx++) {
output.get(y, options.get_wave_width() - 1 + dx) = pattern.get(0, dx);
}
}
for (unsigned x = 0; x < options.get_wave_width(); x++) {
for (uint32_t x = 0; x < options.get_wave_width(); x++) {
const Array2D<T> &pattern = patterns[output_patterns.get(options.get_wave_height() - 1, x)];
for (unsigned dy = 1; dy < options.pattern_size; dy++) {
for (uint32_t dy = 1; dy < options.pattern_size; dy++) {
output.get(options.get_wave_height() - 1 + dy, x) =
pattern.get(dy, 0);
}
@ -217,8 +217,8 @@ private:
const Array2D<T> &pattern = patterns[output_patterns.get(options.get_wave_height() - 1, options.get_wave_width() - 1)];
for (unsigned dy = 1; dy < options.pattern_size; dy++) {
for (unsigned dx = 1; dx < options.pattern_size; dx++) {
for (uint32_t dy = 1; dy < options.pattern_size; dy++) {
for (uint32_t dx = 1; dx < options.pattern_size; dx++) {
output.get(options.get_wave_height() - 1 + dy, options.get_wave_width() - 1 + dx) = pattern.get(dy, dx);
}
}
@ -227,8 +227,8 @@ private:
return output;
}
unsigned get_pattern_id(const Array2D<T> &pattern) {
unsigned *pattern_id = std::find(patterns.begin(), patterns.end(), pattern);
uint32_t get_pattern_id(const Array2D<T> &pattern) {
uint32_t *pattern_id = std::find(patterns.begin(), patterns.end(), pattern);
if (pattern_id != patterns.end()) {
return *pattern_id;
@ -239,8 +239,8 @@ private:
// Set the pattern at a specific position, given its pattern id
// pattern_id needs to be a valid pattern id, and i and j needs to be in the wave range
void set_pattern(unsigned pattern_id, unsigned i, unsigned j) {
for (unsigned p = 0; p < patterns.size(); p++) {
void set_pattern(uint32_t pattern_id, uint32_t i, uint32_t j) {
for (uint32_t p = 0; p < patterns.size(); p++) {
if (pattern_id != p) {
wfc.remove_wave_pattern(i, j, p);
}
@ -254,7 +254,7 @@ public:
// Set the pattern at a specific position.
// Returns false if the given pattern does not exist, or if the
// coordinates are not in the wave
bool set_pattern(const Array2D<T> &pattern, unsigned i, unsigned j) {
bool set_pattern(const Array2D<T> &pattern, uint32_t i, uint32_t j) {
auto pattern_id = get_pattern_id(pattern);
if (pattern_id == std::nullopt || i >= options.get_wave_height() || j >= options.get_wave_width()) {
@ -267,7 +267,7 @@ public:
// Run the WFC algorithm, and return the result if the algorithm succeeded.
Array2D<T> run() {
Array2D<unsigned> result = wfc.run();
Array2D<uint32_t> result = wfc.run();
if (result.width == 0 && result.height == 0) {
return Array2D<T>(0, 0);

View File

@ -4,14 +4,13 @@
void Propagator::init_compatible() {
std::array<int, 4> value;
// We compute the number of pattern compatible in all directions.
for (unsigned y = 0; y < wave_height; y++) {
for (unsigned x = 0; x < wave_width; x++) {
for (unsigned pattern = 0; pattern < patterns_size; pattern++) {
for (uint32_t y = 0; y < wave_height; y++) {
for (uint32_t x = 0; x < wave_width; x++) {
for (uint32_t pattern = 0; pattern < patterns_size; pattern++) {
for (int direction = 0; direction < 4; direction++) {
value[direction] =
static_cast<unsigned>(propagator_state[pattern][get_opposite_direction(direction)]
.size());
value[direction] = static_cast<uint32_t>(propagator_state[pattern][get_opposite_direction(direction)].size());
}
compatible.get(y, x, pattern) = value;
}
}
@ -22,12 +21,12 @@ void Propagator::propagate(Wave &wave) {
// We propagate every element while there is element to propagate.
while (propagating.size() != 0) {
// The cell and pattern that has been set to false.
unsigned y1, x1, pattern;
uint32_t y1, x1, pattern;
std::tie(y1, x1, pattern) = propagating[propagating.size() - 1];
propagating.resize(propagating.size() - 1);
// We propagate the information in all 4 directions.
for (unsigned direction = 0; direction < 4; direction++) {
for (uint32_t direction = 0; direction < 4; direction++) {
// We get the next cell in the direction direction.
int dx = directions_x[direction];
int dy = directions_y[direction];
@ -47,14 +46,14 @@ void Propagator::propagate(Wave &wave) {
}
// The index of the second cell, and the patterns compatible
unsigned i2 = x2 + y2 * wave.width;
const Vector<unsigned> &patterns = propagator_state[pattern][direction];
uint32_t i2 = x2 + y2 * wave.width;
const Vector<uint32_t> &patterns = propagator_state[pattern][direction];
// For every pattern that could be placed in that cell without being in
// contradiction with pattern1
int size = patterns.size();
for (int i = 0; i < size; ++i) {
unsigned int pattern = patterns[i];
uint32_t pattern = patterns[i];
// We decrease the number of compatible patterns in the opposite
// direction If the pattern was discarded from the wave, the element

View File

@ -11,22 +11,22 @@ class Wave;
class Propagator {
public:
using PropagatorState = Vector<std::array<Vector<unsigned>, 4>>;
using PropagatorState = Vector<std::array<Vector<uint32_t>, 4>>;
private:
const uint32_t patterns_size;
PropagatorState propagator_state;
const unsigned wave_width;
const unsigned wave_height;
const uint32_t wave_width;
const uint32_t wave_height;
const bool periodic_output;
// All the tuples (y, x, pattern) that should be propagated.
// The tuple should be propagated when wave.get(y, x, pattern) is set to
// false.
Vector<std::tuple<unsigned, unsigned, unsigned>> propagating;
Vector<std::tuple<uint32_t, uint32_t, uint32_t>> propagating;
// compatible.get(y, x, pattern)[direction] contains the number of patterns
// present in the wave that can be placed in the cell next to (y,x) in the
@ -38,7 +38,7 @@ private:
void init_compatible();
public:
Propagator(unsigned wave_height, unsigned wave_width, bool periodic_output,
Propagator(uint32_t wave_height, uint32_t wave_width, bool periodic_output,
PropagatorState propagator_state) :
patterns_size(propagator_state.size()),
propagator_state(propagator_state),
@ -49,12 +49,12 @@ public:
init_compatible();
}
void add_to_propagator(unsigned y, unsigned x, unsigned pattern) {
void add_to_propagator(uint32_t y, uint32_t x, uint32_t pattern) {
// All the direction are set to 0, since the pattern cannot be set in (y,x).
std::array<int, 4> temp = {};
compatible.get(y, x, pattern) = temp;
propagating.push_back(std::tuple<unsigned, unsigned, unsigned>(y, x, pattern));
propagating.push_back(std::tuple<uint32_t, uint32_t, uint32_t>(y, x, pattern));
}
void propagate(Wave &wave);

View File

@ -22,7 +22,7 @@ enum class Symmetry {
// Return the number of possible distinct orientations for a tile.
// An orientation is a combination of rotations and reflections.
*/
constexpr unsigned nb_of_possible_orientations(const Symmetry &symmetry) {
constexpr uint32_t nb_of_possible_orientations(const Symmetry &symmetry) {
switch (symmetry) {
case Symmetry::X:
return 1;
@ -46,7 +46,7 @@ struct Tile {
// Generate the map associating an orientation id to the orientation
// id obtained when rotating 90° anticlockwise the tile.
static Vector<unsigned> generate_rotation_map(const Symmetry &symmetry) {
static Vector<uint32_t> generate_rotation_map(const Symmetry &symmetry) {
switch (symmetry) {
case Symmetry::X:
return { 0 };
@ -64,7 +64,7 @@ struct Tile {
// Generate the map associating an orientation id to the orientation
// id obtained when reflecting the tile along the x axis.
static Vector<unsigned> generate_reflection_map(const Symmetry &symmetry) {
static Vector<uint32_t> generate_reflection_map(const Symmetry &symmetry) {
switch (symmetry) {
case Symmetry::X:
return { 0 };
@ -87,12 +87,12 @@ struct Tile {
// Actions 0, 1, 2, and 3 are 0°, 90°, 180°, and 270° anticlockwise rotations.
// Actions 4, 5, 6, and 7 are actions 0, 1, 2, and 3 preceded by a reflection
// on the x axis.
static Vector<Vector<unsigned>> generate_action_map(const Symmetry &symmetry) {
Vector<unsigned> rotation_map = generate_rotation_map(symmetry);
Vector<unsigned> reflection_map = generate_reflection_map(symmetry);
static Vector<Vector<uint32_t>> generate_action_map(const Symmetry &symmetry) {
Vector<uint32_t> rotation_map = generate_rotation_map(symmetry);
Vector<uint32_t> reflection_map = generate_reflection_map(symmetry);
size_t size = rotation_map.size();
Vector<Vector<unsigned>> action_map(8,
Vector<unsigned>(size));
Vector<Vector<uint32_t>> action_map(8,
Vector<uint32_t>(size));
for (size_t i = 0; i < size; ++i) {
action_map[0][i] = i;
}
@ -167,29 +167,29 @@ template <typename T>
class TilingWFC {
private:
Vector<Tile<T>> tiles;
Vector<std::pair<unsigned, unsigned>> id_to_oriented_tile;
Vector<Vector<unsigned>> oriented_tile_ids;
Vector<std::pair<uint32_t, uint32_t>> id_to_oriented_tile;
Vector<Vector<uint32_t>> oriented_tile_ids;
TilingWFCOptions options;
WFC wfc;
public:
unsigned height;
unsigned width;
uint32_t height;
uint32_t width;
private:
// Generate mapping from id to oriented tiles and vice versa.
static std::pair<Vector<std::pair<unsigned, unsigned>>,
Vector<Vector<unsigned>>>
static std::pair<Vector<std::pair<uint32_t, uint32_t>>,
Vector<Vector<uint32_t>>>
generate_oriented_tile_ids(const Vector<Tile<T>> &tiles) {
Vector<std::pair<unsigned, unsigned>> id_to_oriented_tile;
Vector<Vector<unsigned>> oriented_tile_ids;
Vector<std::pair<uint32_t, uint32_t>> id_to_oriented_tile;
Vector<Vector<uint32_t>> oriented_tile_ids;
unsigned id = 0;
for (unsigned i = 0; i < tiles.size(); i++) {
uint32_t id = 0;
for (uint32_t i = 0; i < tiles.size(); i++) {
oriented_tile_ids.push_back({});
for (unsigned j = 0; j < tiles[i].data.size(); j++) {
for (uint32_t j = 0; j < tiles[i].data.size(); j++) {
id_to_oriented_tile.push_back({ i, j });
oriented_tile_ids[i].push_back(id);
id++;
@ -200,31 +200,31 @@ private:
}
// Generate the propagator which will be used in the wfc algorithm.
static Vector<std::array<Vector<unsigned>, 4>> generate_propagator(
const Vector<std::tuple<unsigned, unsigned, unsigned, unsigned>> &neighbors,
static Vector<std::array<Vector<uint32_t>, 4>> generate_propagator(
const Vector<std::tuple<uint32_t, uint32_t, uint32_t, uint32_t>> &neighbors,
Vector<Tile<T>> tiles,
Vector<std::pair<unsigned, unsigned>> id_to_oriented_tile,
Vector<Vector<unsigned>> oriented_tile_ids) {
Vector<std::pair<uint32_t, uint32_t>> id_to_oriented_tile,
Vector<Vector<uint32_t>> oriented_tile_ids) {
size_t nb_oriented_tiles = id_to_oriented_tile.size();
Vector<std::array<Vector<bool>, 4>> dense_propagator(
nb_oriented_tiles, { Vector<bool>(nb_oriented_tiles, false), Vector<bool>(nb_oriented_tiles, false), Vector<bool>(nb_oriented_tiles, false), Vector<bool>(nb_oriented_tiles, false) });
for (auto neighbor : neighbors) {
unsigned tile1 = std::get<0>(neighbor);
unsigned orientation1 = std::get<1>(neighbor);
unsigned tile2 = std::get<2>(neighbor);
unsigned orientation2 = std::get<3>(neighbor);
Vector<Vector<unsigned>> action_map1 =
uint32_t tile1 = std::get<0>(neighbor);
uint32_t orientation1 = std::get<1>(neighbor);
uint32_t tile2 = std::get<2>(neighbor);
uint32_t orientation2 = std::get<3>(neighbor);
Vector<Vector<uint32_t>> action_map1 =
Tile<T>::generate_action_map(tiles[tile1].symmetry);
Vector<Vector<unsigned>> action_map2 =
Vector<Vector<uint32_t>> action_map2 =
Tile<T>::generate_action_map(tiles[tile2].symmetry);
auto add = [&](unsigned action, unsigned direction) {
unsigned temp_orientation1 = action_map1[action][orientation1];
unsigned temp_orientation2 = action_map2[action][orientation2];
unsigned oriented_tile_id1 = oriented_tile_ids[tile1][temp_orientation1];
unsigned oriented_tile_id2 = oriented_tile_ids[tile2][temp_orientation2];
auto add = [&](uint32_t action, uint32_t direction) {
uint32_t temp_orientation1 = action_map1[action][orientation1];
uint32_t temp_orientation2 = action_map2[action][orientation2];
uint32_t oriented_tile_id1 = oriented_tile_ids[tile1][temp_orientation1];
uint32_t oriented_tile_id2 = oriented_tile_ids[tile2][temp_orientation2];
dense_propagator[oriented_tile_id1][direction][oriented_tile_id2] = true;
direction = get_opposite_direction(direction);
dense_propagator[oriented_tile_id2][direction][oriented_tile_id1] = true;
@ -240,7 +240,7 @@ private:
add(7, 0);
}
Vector<std::array<Vector<unsigned>, 4>> propagator(nb_oriented_tiles);
Vector<std::array<Vector<uint32_t>, 4>> propagator(nb_oriented_tiles);
for (size_t i = 0; i < nb_oriented_tiles; ++i) {
for (size_t j = 0; j < nb_oriented_tiles; ++j) {
@ -269,16 +269,16 @@ private:
}
// Translate the generic WFC result into the image result
Array2D<T> id_to_tiling(Array2D<unsigned> ids) {
unsigned size = tiles[0].data[0].height;
Array2D<T> id_to_tiling(Array2D<uint32_t> ids) {
uint32_t size = tiles[0].data[0].height;
Array2D<T> tiling(size * ids.height, size * ids.width);
for (unsigned i = 0; i < ids.height; i++) {
for (unsigned j = 0; j < ids.width; j++) {
std::pair<unsigned, unsigned> oriented_tile = id_to_oriented_tile[ids.get(i, j)];
for (uint32_t i = 0; i < ids.height; i++) {
for (uint32_t j = 0; j < ids.width; j++) {
std::pair<uint32_t, uint32_t> oriented_tile = id_to_oriented_tile[ids.get(i, j)];
for (unsigned y = 0; y < size; y++) {
for (unsigned x = 0; x < size; x++) {
for (uint32_t y = 0; y < size; y++) {
for (uint32_t x = 0; x < size; x++) {
tiling.get(i * size + y, j * size + x) = tiles[oriented_tile.first].data[oriented_tile.second].get(y, x);
}
}
@ -288,8 +288,8 @@ private:
return tiling;
}
void set_tile(unsigned tile_id, unsigned i, unsigned j) {
for (unsigned p = 0; p < id_to_oriented_tile.size(); p++) {
void set_tile(uint32_t tile_id, uint32_t i, uint32_t j) {
for (uint32_t p = 0; p < id_to_oriented_tile.size(); p++) {
if (tile_id != p) {
wfc.remove_wave_pattern(i, j, p);
}
@ -300,9 +300,9 @@ public:
// Construct the TilingWFC class to generate a tiled image.
TilingWFC(
const Vector<Tile<T>> &tiles,
const Vector<std::tuple<unsigned, unsigned, unsigned, unsigned>>
const Vector<std::tuple<uint32_t, uint32_t, uint32_t, uint32_t>>
&neighbors,
const unsigned height, const unsigned width,
const uint32_t height, const uint32_t width,
const TilingWFCOptions &options, int seed) :
tiles(tiles),
id_to_oriented_tile(generate_oriented_tile_ids(tiles).first),
@ -318,19 +318,19 @@ public:
// Set the tile at a specific position.
// Returns false if the given tile and orientation does not exist,
// or if the coordinates are not in the wave
bool set_tile(unsigned tile_id, unsigned orientation, unsigned i, unsigned j) {
bool set_tile(uint32_t tile_id, uint32_t orientation, uint32_t i, uint32_t j) {
if (tile_id >= oriented_tile_ids.size() || orientation >= oriented_tile_ids[tile_id].size() || i >= height || j >= width) {
return false;
}
unsigned oriented_tile_id = oriented_tile_ids[tile_id][orientation];
uint32_t oriented_tile_id = oriented_tile_ids[tile_id][orientation];
set_tile(oriented_tile_id, i, j);
return true;
}
// Run the tiling wfc and return the result if the algorithm succeeded
Array2D<T> run() {
Array2D<unsigned> a = wfc.run();
Array2D<uint32_t> a = wfc.run();
if (a.width == 0 && a.height == 0) {
return Array2D<T>(0, 0);

View File

@ -8,7 +8,7 @@ namespace {
Vector<double> get_plogp(const Vector<double> &distribution) {
Vector<double> plogp;
for (unsigned i = 0; i < distribution.size(); i++) {
for (uint32_t i = 0; i < distribution.size(); i++) {
plogp.push_back(distribution[i] * log(distribution[i]));
}
@ -19,7 +19,7 @@ Vector<double> get_plogp(const Vector<double> &distribution) {
double get_min_abs_half(const Vector<double> &v) {
double min_abs_half = std::numeric_limits<double>::infinity();
for (unsigned i = 0; i < v.size(); i++) {
for (uint32_t i = 0; i < v.size(); i++) {
min_abs_half = std::min(min_abs_half, std::abs(v[i] / 2.0));
}
@ -28,7 +28,7 @@ double get_min_abs_half(const Vector<double> &v) {
} // namespace
Wave::Wave(unsigned height, unsigned width,
Wave::Wave(uint32_t height, uint32_t width,
const Vector<double> &patterns_frequencies) :
patterns_frequencies(patterns_frequencies),
plogp_patterns_frequencies(get_plogp(patterns_frequencies)),
@ -44,7 +44,7 @@ Wave::Wave(unsigned height, unsigned width,
double base_entropy = 0;
double base_s = 0;
for (unsigned i = 0; i < nb_patterns; i++) {
for (uint32_t i = 0; i < nb_patterns; i++) {
base_entropy += plogp_patterns_frequencies[i];
base_s += patterns_frequencies[i];
}
@ -62,13 +62,13 @@ Wave::Wave(unsigned height, unsigned width,
memoisation.log_sum.fill(log_base_s);
memoisation.nb_patterns.resize(width * height);
memoisation.nb_patterns.fill(static_cast<unsigned>(nb_patterns));
memoisation.nb_patterns.fill(static_cast<uint32_t>(nb_patterns));
memoisation.entropy.resize(width * height);
memoisation.entropy.fill(entropy_base);
}
void Wave::set(unsigned index, unsigned pattern, bool value) {
void Wave::set(uint32_t index, uint32_t pattern, bool value) {
bool old_value = data.get(index, pattern);
// If the value isn't changed, nothing needs to be done.
@ -101,7 +101,7 @@ int Wave::get_min_entropy(std::minstd_rand &gen) const {
double min = std::numeric_limits<double>::infinity();
int argmin = -1;
for (unsigned i = 0; i < size; i++) {
for (uint32_t i = 0; i < size; i++) {
// If the cell is decided, we do not compute the entropy (which is equal
// to 0).
double nb_patterns_local = memoisation.nb_patterns[i];

View File

@ -13,7 +13,7 @@ struct EntropyMemoisation {
Vector<double> plogp_sum; // The sum of p'(pattern)// log(p'(pattern)).
Vector<double> sum; // The sum of p'(pattern).
Vector<double> log_sum; // The log of sum.
Vector<unsigned> nb_patterns; // The number of patterns present
Vector<uint32_t> nb_patterns; // The number of patterns present
Vector<double> entropy; // The entropy of the cell.
};
@ -45,28 +45,28 @@ private:
public:
// The size of the wave.
const unsigned width;
const unsigned height;
const unsigned size;
const uint32_t width;
const uint32_t height;
const uint32_t size;
// Initialize the wave with every cell being able to have every pattern.
Wave(unsigned height, unsigned width, const Vector<double> &patterns_frequencies);
Wave(uint32_t height, uint32_t width, const Vector<double> &patterns_frequencies);
// Return true if pattern can be placed in cell index.
bool get(unsigned index, unsigned pattern) const {
bool get(uint32_t index, uint32_t pattern) const {
return data.get(index, pattern);
}
// Return true if pattern can be placed in cell (i,j)
bool get(unsigned i, unsigned j, unsigned pattern) const {
bool get(uint32_t i, uint32_t j, uint32_t pattern) const {
return get(i * width + j, pattern);
}
// Set the value of pattern in cell index.
void set(unsigned index, unsigned pattern, bool value);
void set(uint32_t index, uint32_t pattern, bool value);
// Set the value of pattern in cell (i,j).
void set(unsigned i, unsigned j, unsigned pattern, bool value) {
void set(uint32_t i, uint32_t j, uint32_t pattern, bool value) {
set(i * width + j, pattern, value);
}

View File

@ -21,11 +21,11 @@ Vector<double> &normalize(Vector<double> &v) {
}
} //namespace
Array2D<unsigned> WFC::wave_to_output() const {
Array2D<unsigned> output_patterns(wave.height, wave.width);
Array2D<uint32_t> WFC::wave_to_output() const {
Array2D<uint32_t> output_patterns(wave.height, wave.width);
for (unsigned i = 0; i < wave.size; i++) {
for (unsigned k = 0; k < nb_patterns; k++) {
for (uint32_t i = 0; i < wave.size; i++) {
for (uint32_t k = 0; k < nb_patterns; k++) {
if (wave.get(i, k)) {
output_patterns.data.write[i] = k;
}
@ -36,18 +36,18 @@ Array2D<unsigned> WFC::wave_to_output() const {
WFC::WFC(bool periodic_output, int seed,
Vector<double> patterns_frequencies,
Propagator::PropagatorState propagator, unsigned wave_height,
unsigned wave_width) :
Propagator::PropagatorState propagator, uint32_t wave_height,
uint32_t wave_width) :
gen(seed), patterns_frequencies(normalize(patterns_frequencies)), wave(wave_height, wave_width, patterns_frequencies), nb_patterns(propagator.size()), propagator(wave.height, wave.width, periodic_output, propagator) {}
Array2D<unsigned> WFC::run() {
Array2D<uint32_t> WFC::run() {
while (true) {
// Define the value of an undefined cell.
ObserveStatus result = observe();
// Check if the algorithm has terminated.
if (result == failure) {
return Array2D<unsigned>(0, 0);
return Array2D<uint32_t>(0, 0);
} else if (result == success) {
return wave_to_output();
}
@ -75,7 +75,7 @@ WFC::ObserveStatus WFC::observe() {
// Choose an element according to the pattern distribution
double s = 0;
for (unsigned k = 0; k < nb_patterns; k++) {
for (uint32_t k = 0; k < nb_patterns; k++) {
s += wave.get(argmin, k) ? patterns_frequencies[k] : 0;
}
@ -83,7 +83,7 @@ WFC::ObserveStatus WFC::observe() {
double random_value = dis(gen);
size_t chosen_value = nb_patterns - 1;
for (unsigned k = 0; k < nb_patterns; k++) {
for (uint32_t k = 0; k < nb_patterns; k++) {
random_value -= wave.get(argmin, k) ? patterns_frequencies[k] : 0;
if (random_value <= 0) {
chosen_value = k;
@ -92,7 +92,7 @@ WFC::ObserveStatus WFC::observe() {
}
// And define the cell with the pattern.
for (unsigned k = 0; k < nb_patterns; k++) {
for (uint32_t k = 0; k < nb_patterns; k++) {
if (wave.get(argmin, k) != (k == chosen_value)) {
propagator.add_to_propagator(argmin / wave.width, argmin % wave.width, k);
wave.set(argmin, k, false);

View File

@ -28,16 +28,16 @@ private:
// Transform the wave to a valid output (a 2d array of patterns that aren't in
// contradiction). This function should be used only when all cell of the wave
// are defined.
Array2D<unsigned> wave_to_output() const;
Array2D<uint32_t> wave_to_output() const;
public:
// Basic constructor initializing the algorithm.
WFC(bool periodic_output, int seed, Vector<double> patterns_frequencies,
Propagator::PropagatorState propagator, unsigned wave_height,
unsigned wave_width);
Propagator::PropagatorState propagator, uint32_t wave_height,
uint32_t wave_width);
// Run the algorithm, and return a result if it succeeded.
Array2D<unsigned> run();
Array2D<uint32_t> run();
// Return value of observe.
enum ObserveStatus {
@ -53,7 +53,7 @@ public:
void propagate() { propagator.propagate(wave); }
// Remove pattern from cell (i,j).
void remove_wave_pattern(unsigned i, unsigned j, unsigned pattern) {
void remove_wave_pattern(uint32_t i, uint32_t j, uint32_t pattern) {
if (wave.get(i, j, pattern)) {
wave.set(i, j, pattern, false);
propagator.add_to_propagator(i, j, pattern);