finally all working
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1 +1,4 @@
|
|||||||
/build
|
/build
|
||||||
|
/emcc_build
|
||||||
|
/debug
|
||||||
|
.vscode
|
||||||
|
|||||||
@@ -1,10 +1,14 @@
|
|||||||
cmake_minimum_required(VERSION 3.18)
|
cmake_minimum_required(VERSION 3.24)
|
||||||
project(somaesque)
|
project(somaesque)
|
||||||
|
|
||||||
|
|
||||||
|
set(CMAKE_BUILD_TYPE Release)
|
||||||
|
set(CMAKE_CXX_FLAGS_RELEASE "-O3")
|
||||||
|
|
||||||
#find_package(glfw3 3.3 REQUIRED)
|
#find_package(glfw3 3.3 REQUIRED)
|
||||||
#find_package(glm REQUIRED)
|
#find_package(glm REQUIRED)
|
||||||
set(CMAKE_CXX_STANDARD 17)
|
set(CMAKE_CXX_STANDARD 20)
|
||||||
set(CMAKE_CXX_FLAGS -I/usr/include/SDL2)
|
#set(CMAKE_CXX_FLAGS -I/usr/include/SDL2)
|
||||||
|
|
||||||
add_executable(somaesque
|
add_executable(somaesque
|
||||||
main.cpp
|
main.cpp
|
||||||
@@ -32,7 +36,7 @@ add_executable(tests
|
|||||||
target_link_libraries(
|
target_link_libraries(
|
||||||
tests
|
tests
|
||||||
GTest::gtest_main
|
GTest::gtest_main
|
||||||
)
|
)
|
||||||
|
|
||||||
include(GoogleTest)
|
include(GoogleTest)
|
||||||
gtest_discover_tests(tests)
|
gtest_discover_tests(tests)
|
||||||
|
|||||||
190
VoxelSpace.cpp
190
VoxelSpace.cpp
@@ -1,46 +1,48 @@
|
|||||||
#include "VoxelSpace.h"
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <bitset>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include "VoxelSpace.h"
|
||||||
|
|
||||||
namespace Voxel {
|
namespace Voxel {
|
||||||
inline auto index(int dims[3], int x, int y, int z) -> int {
|
auto index(int dim_y, int dim_z, int x, int y, int z) -> int {
|
||||||
return (dims[1] * dims[2] * x + dims[2] * y + z);
|
return dim_y * dim_z * x + dim_z * y + z;
|
||||||
}
|
}
|
||||||
|
|
||||||
// [1, 0, 0] [x] [ x]
|
// [1, 0, 0] [x] [ x]
|
||||||
// [0, 0, -1] * [y] = [-z]
|
// [0, 0, -1] * [y] = [-z]
|
||||||
// [0, 1, 0] [z] [ y]
|
// [0, 1, 0] [z] [ y]
|
||||||
inline auto newIndexRotX(int dims[3], int x, int y, int z) -> int {
|
auto newIndexRotX(Space *space, int x, int y, int z) -> int {
|
||||||
return dims[2] * dims[1] * x + dims[1] * (dims[2] - 1 - z) + y;
|
return space->dim_z * space->dim_y * x + space->dim_y * (space->dim_z - 1 - z) + y;
|
||||||
}
|
}
|
||||||
|
|
||||||
// [ 0, 0, 1] [x] [ z]
|
// [ 0, 0, 1] [x] [ z]
|
||||||
// [ 0, 1, 0] * [y] = [ y]
|
// [ 0, 1, 0] * [y] = [ y]
|
||||||
// [-1, 0, 0] [z] [-x]
|
// [-1, 0, 0] [z] [-x]
|
||||||
inline auto newIndexRotY(int dims[3], int x, int y, int z) -> int {
|
auto newIndexRotY(Space *space, int x, int y, int z) -> int {
|
||||||
return dims[1] * dims[0] * z + dims[0] * y + (dims[0] - 1 - x);
|
return space->dim_y * space->dim_x * z + space->dim_x * y + (space->dim_x - 1 - x);
|
||||||
}
|
}
|
||||||
|
|
||||||
// [0, -1, 0] [x] [-y]
|
// [0, -1, 0] [x] [-y]
|
||||||
// [1, 0, 0] * [y] = [ x]
|
// [1, 0, 0] * [y] = [ x]
|
||||||
// [0, 0, 1] [z] [ z]
|
// [0, 0, 1] [z] [ z]
|
||||||
inline auto newIndexRotZ(int dims[3], int x, int y, int z) -> int {
|
auto newIndexRotZ(Space *space, int x, int y, int z) -> int {
|
||||||
return dims[0] * dims[2] * (dims[1] - 1 - y) + dims[2] * x + z;
|
return space->dim_x * space->dim_z * (space->dim_y - 1 - y) + space->dim_z * x + z;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline auto toggle(uint64_t space, int index) -> uint64_t {
|
auto toggle(uint64_t space, int index) -> uint64_t {
|
||||||
space ^= 1ull << index;
|
space ^= 1ul << index;
|
||||||
return space;
|
return space;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline auto set(uint64_t *space, int index, bool val) -> void {
|
auto set(uint64_t space, int index, bool val) -> uint64_t {
|
||||||
if (val) {
|
if (val) {
|
||||||
*space |= 1ull << index;
|
space |= 1ul << index;
|
||||||
} else {
|
} else {
|
||||||
*space &= ~(1ull << index);
|
space &= ~(1ul << index);
|
||||||
}
|
}
|
||||||
|
return space;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto collides(uint64_t a, uint64_t b) -> bool {
|
auto collides(uint64_t a, uint64_t b) -> bool {
|
||||||
@@ -51,25 +53,25 @@ namespace Voxel {
|
|||||||
return (a->space | b->space) != (a->space ^ b->space);
|
return (a->space | b->space) != (a->space ^ b->space);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline auto filledAt(uint64_t space, int dims[3], int x, int y, int z) -> bool {
|
auto filledAt(Space *space, int x, int y, int z) -> bool {
|
||||||
auto mask = 1ull << (dims[1] * dims[2] * x + dims[2] * y + z);
|
auto mask = 1ul << (space->dim_y * space->dim_z * x + space->dim_z * y + z);
|
||||||
return (space & mask) != 0ull;
|
return (space->space & mask) != 0ul;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto getExtrema(uint64_t space, int dims[3]) -> Extrema {
|
auto getExtrema(Space *space) -> Extrema {
|
||||||
auto extrema = Extrema{
|
auto extrema = Extrema{
|
||||||
.xMax=0,
|
.xMax=0,
|
||||||
.xMin=dims[0],
|
.xMin=space->dim_x,
|
||||||
.yMax=0,
|
.yMax=0,
|
||||||
.yMin=dims[1],
|
.yMin=space->dim_y,
|
||||||
.zMax=0,
|
.zMax=0,
|
||||||
.zMin=dims[2],
|
.zMin=space->dim_z,
|
||||||
};
|
};
|
||||||
|
|
||||||
for (int x = 0; x < dims[0]; x++) {
|
for (int x = 0; x < space->dim_x; x++) {
|
||||||
for (int y = 0; y < dims[1]; y++) {
|
for (int y = 0; y < space->dim_y; y++) {
|
||||||
for (int z = 0; z < dims[2]; z++) {
|
for (int z = 0; z < space->dim_z; z++) {
|
||||||
if (filledAt(space, dims, x, y, z)) {
|
if (filledAt(space, x, y, z)) {
|
||||||
if (x > extrema.xMax) extrema.xMax = x;
|
if (x > extrema.xMax) extrema.xMax = x;
|
||||||
if (x < extrema.xMin) extrema.xMin = x;
|
if (x < extrema.xMin) extrema.xMin = x;
|
||||||
if (y > extrema.yMax) extrema.yMax = y;
|
if (y > extrema.yMax) extrema.yMax = y;
|
||||||
@@ -85,81 +87,81 @@ namespace Voxel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto cullEmptySpace(Space *space) -> void {
|
auto cullEmptySpace(Space *space) -> void {
|
||||||
auto extrema = getExtrema(space->space, space->dims);
|
auto extrema = getExtrema(space);
|
||||||
auto space_index = 0;
|
auto space_index = 0;
|
||||||
auto newSpace = 0ull;
|
auto newSpace = 0ul;
|
||||||
for (int x = extrema.xMin; x <= extrema.xMax; x++) {
|
for (int x = extrema.xMin; x <= extrema.xMax; x++) {
|
||||||
for (int y = extrema.yMin; y <= extrema.yMax; y++) {
|
for (int y = extrema.yMin; y <= extrema.yMax; y++) {
|
||||||
for (int z = extrema.zMin; z <= extrema.zMax; z++) {
|
for (int z = extrema.zMin; z <= extrema.zMax; z++) {
|
||||||
if (filledAt(space->space, space->dims, x, y, z)) {
|
if (filledAt(space, x, y, z)) {
|
||||||
newSpace |= 1ull << space_index;
|
newSpace |= 1ul << space_index;
|
||||||
}
|
}
|
||||||
space_index++;
|
space_index++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
space->dims[0] = extrema.xMax - extrema.xMin + 1;
|
space->dim_x = extrema.xMax - extrema.xMin + 1;
|
||||||
space->dims[1] = extrema.yMax - extrema.yMin + 1;
|
space->dim_y = extrema.yMax - extrema.yMin + 1;
|
||||||
space->dims[2] = extrema.zMax - extrema.zMin + 1;
|
space->dim_z = extrema.zMax - extrema.zMin + 1;
|
||||||
space->space = newSpace;
|
space->space = newSpace;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto rotate90X(Space *space) -> void {
|
auto rotate90X(Space *space) -> void {
|
||||||
auto new_space = 0ull;
|
auto new_space = 0ul;
|
||||||
for (int x = 0; x < space->dims[0]; x++) {
|
for (int x = 0; x < space->dim_x; x++) {
|
||||||
for (int y = 0; y < space->dims[1]; y++) {
|
for (int y = 0; y < space->dim_y; y++) {
|
||||||
for (int z = 0; z < space->dims[2]; z++) {
|
for (int z = 0; z < space->dim_z; z++) {
|
||||||
if (filledAt(space->space, space->dims, x, y, z)) {
|
if (filledAt(space, x, y, z)) {
|
||||||
new_space |= 1 << newIndexRotX(space->dims, x, y, z);
|
new_space |= 1 << newIndexRotX(space, x, y, z);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
auto temp = space->dims[1];
|
auto temp = space->dim_y;
|
||||||
space->dims[1] = space->dims[2];
|
space->dim_y = space->dim_z;
|
||||||
space->dims[2] = temp;
|
space->dim_z = temp;
|
||||||
space->space = new_space;
|
space->space = new_space;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto rotate90Y(Space *space) -> void {
|
auto rotate90Y(Space *space) -> void {
|
||||||
auto new_space = 0ull;
|
auto new_space = 0ul;
|
||||||
for (int x = 0; x < space->dims[0]; x++) {
|
for (int x = 0; x < space->dim_x; x++) {
|
||||||
for (int y = 0; y < space->dims[1]; y++) {
|
for (int y = 0; y < space->dim_y; y++) {
|
||||||
for (int z = 0; z < space->dims[2]; z++) {
|
for (int z = 0; z < space->dim_z; z++) {
|
||||||
if (filledAt(space->space, space->dims, x, y, z)) {
|
if (filledAt(space, x, y, z)) {
|
||||||
new_space |= 1 << newIndexRotY(space->dims, x, y, z);
|
new_space |= 1 << newIndexRotY(space, x, y, z);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
auto temp = space->dims[0];
|
auto temp = space->dim_x;
|
||||||
space->dims[0] = space->dims[2];
|
space->dim_x = space->dim_z;
|
||||||
space->dims[2] = temp;
|
space->dim_z = temp;
|
||||||
space->space = new_space;
|
space->space = new_space;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto rotate90Z(Space *space) -> void {
|
auto rotate90Z(Space *space) -> void {
|
||||||
auto new_space = 0ull;
|
auto new_space = 0ul;
|
||||||
for (int x = 0; x < space->dims[0]; x++) {
|
for (int x = 0; x < space->dim_x; x++) {
|
||||||
for (int y = 0; y < space->dims[1]; y++) {
|
for (int y = 0; y < space->dim_y; y++) {
|
||||||
for (int z = 0; z < space->dims[2]; z++) {
|
for (int z = 0; z < space->dim_z; z++) {
|
||||||
if (filledAt(space->space, space->dims, x, y, z)) {
|
if (filledAt(space, x, y, z)) {
|
||||||
new_space |= 1 << newIndexRotZ(space->dims, x, y, z);
|
new_space |= 1 << newIndexRotZ(space, x, y, z);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
auto temp = space->dims[0];
|
auto temp = space->dim_x;
|
||||||
space->dims[0] = space->dims[1];
|
space->dim_x = space->dim_y;
|
||||||
space->dims[1] = temp;
|
space->dim_y = temp;
|
||||||
space->space = new_space;
|
space->space = new_space;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline auto isMatch(Space *a, Space *b) -> bool {
|
auto isMatch(Space *a, Space *b) -> bool {
|
||||||
return a->space == b->space
|
return a->space == b->space
|
||||||
&& a->dims[0] == b->dims[0]
|
&& a->dim_x == b->dim_x
|
||||||
&& a->dims[1] == b->dims[1]
|
&& a->dim_y == b->dim_y
|
||||||
&& a->dims[2] == b->dims[2];
|
&& a->dim_z == b->dim_z;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pushNewUniqueSpins(std::vector<Space> *existingSpaces, Space* spaceToSpin) -> void {
|
auto pushNewUniqueSpins(std::vector<Space> *existingSpaces, Space* spaceToSpin) -> void {
|
||||||
@@ -185,7 +187,7 @@ namespace Voxel {
|
|||||||
|
|
||||||
auto pushXAxisSpins(std::vector<Space> *existingSpaces, Space* spaceToSpin) -> void {
|
auto pushXAxisSpins(std::vector<Space> *existingSpaces, Space* spaceToSpin) -> void {
|
||||||
auto refSpace = *spaceToSpin;
|
auto refSpace = *spaceToSpin;
|
||||||
for (int i = 0; i < 3; i++) {
|
for (int i = 0; i < 4; i++) {
|
||||||
rotate90X(&refSpace);
|
rotate90X(&refSpace);
|
||||||
existingSpaces->push_back(refSpace);
|
existingSpaces->push_back(refSpace);
|
||||||
}
|
}
|
||||||
@@ -193,30 +195,14 @@ namespace Voxel {
|
|||||||
|
|
||||||
auto getUniqueRotations(Space *space) -> std::vector<Space> {
|
auto getUniqueRotations(Space *space) -> std::vector<Space> {
|
||||||
auto rotations = std::vector<Space>();
|
auto rotations = std::vector<Space>();
|
||||||
rotations.reserve(6*24);
|
rotations.reserve(24);
|
||||||
auto dims = space->dims;
|
|
||||||
auto refSpace = *space;
|
auto refSpace = *space;
|
||||||
|
cullEmptySpace(&refSpace);
|
||||||
pushNewUniqueSpins(&rotations, &refSpace);
|
pushNewUniqueSpins(&rotations, &refSpace);
|
||||||
rotate90Y(&refSpace);
|
rotate90Y(&refSpace);
|
||||||
pushNewUniqueSpins(&rotations, &refSpace);
|
pushNewUniqueSpins(&rotations, &refSpace);
|
||||||
rotate90Y(&refSpace);
|
rotate90Y(&refSpace);
|
||||||
pushNewUniqueSpins(&rotations, &refSpace);
|
pushNewUniqueSpins(&rotations, &refSpace);
|
||||||
rotate90Z(&refSpace);
|
|
||||||
pushNewUniqueSpins(&rotations, &refSpace);
|
|
||||||
rotate90Z(&refSpace);
|
|
||||||
rotate90Z(&refSpace);
|
|
||||||
pushNewUniqueSpins(&rotations, &refSpace);
|
|
||||||
return rotations;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto getUniqueRotations(Space *space) -> std::vector<Space> {
|
|
||||||
auto rotations = std::vector<Space>();
|
|
||||||
rotations.reserve(6*24);
|
|
||||||
auto dims = space->dims;
|
|
||||||
auto refSpace = *space;
|
|
||||||
pushNewUniqueSpins(&rotations, &refSpace);
|
|
||||||
rotate90Y(&refSpace);
|
|
||||||
pushNewUniqueSpins(&rotations, &refSpace);
|
|
||||||
rotate90Y(&refSpace);
|
rotate90Y(&refSpace);
|
||||||
pushNewUniqueSpins(&rotations, &refSpace);
|
pushNewUniqueSpins(&rotations, &refSpace);
|
||||||
rotate90Z(&refSpace);
|
rotate90Z(&refSpace);
|
||||||
@@ -229,41 +215,41 @@ namespace Voxel {
|
|||||||
|
|
||||||
auto getAllRotations(Space *space) -> std::vector<Space> {
|
auto getAllRotations(Space *space) -> std::vector<Space> {
|
||||||
auto rotations = std::vector<Space>();
|
auto rotations = std::vector<Space>();
|
||||||
rotations.reserve(6*24);
|
rotations.reserve(24);
|
||||||
auto dims = space->dims;
|
|
||||||
auto refSpace = *space;
|
auto refSpace = *space;
|
||||||
pushXAxisSpins(&rotations, &refSpace);
|
pushXAxisSpins(&rotations, &refSpace);
|
||||||
rotate90Y(&refSpace);
|
rotate90Y(&refSpace);
|
||||||
pushXAxisSpins(&rotations, &refSpace);
|
pushXAxisSpins(&rotations, &refSpace);
|
||||||
rotate90Y(&refSpace);
|
rotate90Y(&refSpace);
|
||||||
pushNewUniqueSpins(&rotations, &refSpace);
|
pushXAxisSpins(&rotations, &refSpace);
|
||||||
|
rotate90Y(&refSpace);
|
||||||
|
pushXAxisSpins(&rotations, &refSpace);
|
||||||
rotate90Z(&refSpace);
|
rotate90Z(&refSpace);
|
||||||
pushNewUniqueSpins(&rotations, &refSpace);
|
pushXAxisSpins(&rotations, &refSpace);
|
||||||
rotate90Z(&refSpace);
|
rotate90Z(&refSpace);
|
||||||
rotate90Z(&refSpace);
|
rotate90Z(&refSpace);
|
||||||
pushNewUniqueSpins(&rotations, &refSpace);
|
pushXAxisSpins(&rotations, &refSpace);
|
||||||
return rotations;
|
return rotations;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto getAllPositionsInPrism(uint64_t space, int space_dims[3], int prism_dims[3]) -> std::vector<uint64_t> {
|
auto getAllPositionsInPrism(Space *space, int prism_dims[3]) -> std::vector<uint64_t> {
|
||||||
auto cubePositions = std::vector<uint64_t>();
|
auto cubePositions = std::vector<uint64_t>();
|
||||||
if (space_dims[0] > prism_dims[0] || space_dims[1] > prism_dims[1] || space_dims[2] > prism_dims[2]) {
|
if (space->dim_x > prism_dims[0] || space->dim_y > prism_dims[1] || space->dim_z > prism_dims[2]) {
|
||||||
return cubePositions;
|
return cubePositions;
|
||||||
}
|
}
|
||||||
auto xPositionCount = prism_dims[0] - space_dims[0] + 1;
|
auto xPositionCount = prism_dims[0] - space->dim_x + 1;
|
||||||
auto yPositionCount = prism_dims[1] - space_dims[1] + 1;
|
auto yPositionCount = prism_dims[1] - space->dim_y + 1;
|
||||||
auto zPositionCount = prism_dims[2] - space_dims[2] + 1;
|
auto zPositionCount = prism_dims[2] - space->dim_z + 1;
|
||||||
cubePositions.reserve(xPositionCount + yPositionCount + zPositionCount);
|
|
||||||
for (int x = 0; x < xPositionCount; x++) {
|
for (int x = 0; x < xPositionCount; x++) {
|
||||||
for (int y = 0; y < yPositionCount; y++) {
|
for (int y = 0; y < yPositionCount; y++) {
|
||||||
for (int z = 0; z < zPositionCount; z++) {
|
for (int z = 0; z < zPositionCount; z++) {
|
||||||
auto new_space = space;
|
auto new_space = 0ul;
|
||||||
for (int posX = 0; posX < space_dims[0]; posX++) {
|
for (int posX = 0; posX < space->dim_x; posX++) {
|
||||||
for (int posY = 0; posY < space_dims[1]; posY++) {
|
for (int posY = 0; posY < space->dim_y; posY++) {
|
||||||
for (int posZ = 0; posZ < space_dims[2]; posZ++) {
|
for (int posZ = 0; posZ < space->dim_z; posZ++) {
|
||||||
auto set_val = filledAt(space, space_dims, x, y, z);
|
auto set_val = filledAt(space, posX, posY, posZ);
|
||||||
auto index_to_set = index(space_dims, x + posX, y + posY, z + posZ);
|
auto index_to_set = index(prism_dims[1], prism_dims[2], x + posX, y + posY, z + posZ);
|
||||||
set(&new_space, index_to_set, set_val);
|
new_space = set(new_space, index_to_set, set_val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -278,7 +264,7 @@ namespace Voxel {
|
|||||||
auto rotations = getUniqueRotations(space);
|
auto rotations = getUniqueRotations(space);
|
||||||
auto result = std::vector<uint64_t>();
|
auto result = std::vector<uint64_t>();
|
||||||
for (auto &rotation : rotations) {
|
for (auto &rotation : rotations) {
|
||||||
auto positions = getAllPositionsInPrism(rotation.space, rotation.dims, prism_dims);
|
auto positions = getAllPositionsInPrism(&rotation, prism_dims);
|
||||||
result.insert(result.end(), positions.begin(), positions.end());
|
result.insert(result.end(), positions.begin(), positions.end());
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
@@ -287,7 +273,7 @@ namespace Voxel {
|
|||||||
auto size(uint64_t space) -> int {
|
auto size(uint64_t space) -> int {
|
||||||
auto size = 0;
|
auto size = 0;
|
||||||
for (int i = 0; i < 64; i++) {
|
for (int i = 0; i < 64; i++) {
|
||||||
if ((space & (1ull << i)) != 0) {
|
if ((space & (1ul << i)) != 0) {
|
||||||
size++;
|
size++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
22
VoxelSpace.h
22
VoxelSpace.h
@@ -5,6 +5,8 @@
|
|||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
namespace Voxel {
|
namespace Voxel {
|
||||||
|
constexpr int NUM_ROTS_3D = 24;
|
||||||
|
|
||||||
struct Extrema {
|
struct Extrema {
|
||||||
int xMax;
|
int xMax;
|
||||||
int xMin;
|
int xMin;
|
||||||
@@ -16,16 +18,16 @@ namespace Voxel {
|
|||||||
|
|
||||||
struct Space {
|
struct Space {
|
||||||
uint64_t space;
|
uint64_t space;
|
||||||
int dims[3];
|
int dim_x;
|
||||||
|
int dim_y;
|
||||||
|
int dim_z;
|
||||||
};
|
};
|
||||||
|
|
||||||
auto index(int dims[3], int x, int y, int z) -> int;
|
auto newIndexRotX(Space *space, int x, int y, int z) -> int;
|
||||||
|
|
||||||
auto newIndexRotX(int dims[3], int x, int y, int z) -> int;
|
auto newIndexRotY(Space *space, int x, int y, int z) -> int;
|
||||||
|
|
||||||
auto newIndexRotY(int dims[3], int x, int y, int z) -> int;
|
auto newIndexRotZ(Space *space, int x, int y, int z) -> int;
|
||||||
|
|
||||||
auto newIndexRotZ(int dims[3], int x, int y, int z) -> int;
|
|
||||||
|
|
||||||
auto toggle(uint64_t space, int index) -> uint64_t;
|
auto toggle(uint64_t space, int index) -> uint64_t;
|
||||||
|
|
||||||
@@ -36,9 +38,9 @@ namespace Voxel {
|
|||||||
|
|
||||||
auto add(Space *a, Space *b) -> Space;
|
auto add(Space *a, Space *b) -> Space;
|
||||||
|
|
||||||
auto filledAt(uint64_t space, int dims[3], int x, int y, int z) -> bool;
|
auto filledAt(Space *space, int x, int y, int z) -> bool;
|
||||||
|
|
||||||
auto getExtrema(uint64_t space, int dims[3]) -> Extrema;
|
auto getExtrema(Space *space) -> Extrema;
|
||||||
|
|
||||||
auto cullEmptySpace(Space *space) -> void;
|
auto cullEmptySpace(Space *space) -> void;
|
||||||
|
|
||||||
@@ -54,7 +56,9 @@ namespace Voxel {
|
|||||||
|
|
||||||
auto getUniqueRotations(Space *space) -> std::vector<Space>;
|
auto getUniqueRotations(Space *space) -> std::vector<Space>;
|
||||||
|
|
||||||
auto getAllPositionsInPrism(uint64_t space, int space_dims[3], int prism_dims[3]) -> std::vector<uint64_t>;
|
auto getAllRotations(Space *space) -> std::vector<Space>;
|
||||||
|
|
||||||
|
auto getAllPositionsInPrism(Space *space, int prism_dims[3]) -> std::vector<uint64_t>;
|
||||||
|
|
||||||
auto getAllPermutationsInPrism(Space *space, int prism_dims[3]) -> std::vector<uint64_t>;
|
auto getAllPermutationsInPrism(Space *space, int prism_dims[3]) -> std::vector<uint64_t>;
|
||||||
|
|
||||||
|
|||||||
145
main.cpp
145
main.cpp
@@ -1,4 +1,5 @@
|
|||||||
#include <bitset>
|
#include <bitset>
|
||||||
|
#include <span>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
@@ -6,6 +7,14 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include "VoxelSpace.h"
|
#include "VoxelSpace.h"
|
||||||
|
|
||||||
|
using SomaSolution = std::vector<uint64_t>;
|
||||||
|
|
||||||
|
struct Solver {
|
||||||
|
std::vector<uint64_t>* input;
|
||||||
|
std::vector<int>* offsets;
|
||||||
|
std::vector<SomaSolution>* solutions;
|
||||||
|
};
|
||||||
|
|
||||||
auto backtrack_solve_iter(std::vector<uint64_t> *polycube_input, std::vector<int> *offsets)-> void {
|
auto backtrack_solve_iter(std::vector<uint64_t> *polycube_input, std::vector<int> *offsets)-> void {
|
||||||
auto num_inputs = offsets->size() - 1;
|
auto num_inputs = offsets->size() - 1;
|
||||||
|
|
||||||
@@ -14,7 +23,7 @@ auto backtrack_solve_iter(std::vector<uint64_t> *polycube_input, std::vector<int
|
|||||||
auto iter_stack = std::vector<int>();
|
auto iter_stack = std::vector<int>();
|
||||||
auto curr_soln_stack = std::vector<int>();
|
auto curr_soln_stack = std::vector<int>();
|
||||||
auto soln_spaces_stack = std::vector<uint64_t>();
|
auto soln_spaces_stack = std::vector<uint64_t>();
|
||||||
soln_spaces_stack.push_back(0ull);
|
soln_spaces_stack.push_back(0ul);
|
||||||
|
|
||||||
auto depth = 0;
|
auto depth = 0;
|
||||||
|
|
||||||
@@ -54,47 +63,76 @@ auto backtrack_solve_iter(std::vector<uint64_t> *polycube_input, std::vector<int
|
|||||||
std::cout << "Done. Found " << solns.size() << " solutions." << std::endl;
|
std::cout << "Done. Found " << solns.size() << " solutions." << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto backtrack_solve(std::vector<uint64_t> *polycube_input, std::vector<int> *offsets, uint64_t working_solution = 0ull, int set = 0) -> int {
|
auto backtrack_solve(Solver *solver, uint64_t working_solution = 0ul, int curr_piece = 0) -> void {
|
||||||
auto solns = 0;
|
auto input = solver->input;
|
||||||
auto start = offsets->at(set);
|
auto offsets = solver->offsets;
|
||||||
auto end = offsets->at(set + 1);
|
auto solutions = solver->solutions;
|
||||||
|
auto start = offsets->at(curr_piece);
|
||||||
|
auto end = offsets->at(curr_piece + 1);
|
||||||
|
auto num_pieces = offsets->size() - 1;
|
||||||
for (int i = start; i < end; i++) {
|
for (int i = start; i < end; i++) {
|
||||||
auto successful_fuse = !Voxel::collides(working_solution, polycube_input->at(i));
|
auto successful_fuse = !Voxel::collides(working_solution, input->at(i));
|
||||||
if (successful_fuse) {
|
if (successful_fuse) {
|
||||||
working_solution = working_solution | polycube_input->at(i);
|
auto new_working_solution = working_solution | input->at(i);
|
||||||
if (set == offsets->size() - 2) {
|
solutions->back().at(curr_piece) = input->at(i);
|
||||||
return solns + 1;
|
if (curr_piece == num_pieces - 1) {
|
||||||
|
auto last_soln = solutions->back();
|
||||||
|
solutions->push_back(SomaSolution(last_soln.begin(), last_soln.end()));
|
||||||
|
return;
|
||||||
} else {
|
} else {
|
||||||
solns += backtrack_solve(polycube_input, offsets, working_solution, set + 1);
|
backtrack_solve(solver, new_working_solution, curr_piece + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return solns;
|
if (curr_piece == 0) {
|
||||||
|
solutions->pop_back();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto filter_unique(std::vector<std::vector<uint64_t>> *solutions, int dims[3]) -> std::vector<std::vector<uint64_t>> {
|
auto get_solution_rotations(SomaSolution *solution, int dims[3]) -> std::vector<SomaSolution> {
|
||||||
if (solutions->size() == 0) {
|
auto result = std::vector<SomaSolution>(Voxel::NUM_ROTS_3D);
|
||||||
return std::vector<std::vector<uint64_t>>();
|
for (int piece_i = 0; piece_i < solution->size(); piece_i++) {
|
||||||
}
|
auto space = Voxel::Space{
|
||||||
auto unique_solns = std::vector<std::vector<uint64_t>>();
|
.space=solution->at(piece_i),
|
||||||
for (auto &solution : unique_solns) {
|
.dim_x=dims[0],
|
||||||
auto foundMatch = false;
|
.dim_y=dims[1],
|
||||||
auto soln_rotations = std::vector<std::vector<uint64_t>>();
|
.dim_z=dims[2],
|
||||||
for (auto &piece : solution) {
|
};
|
||||||
auto space = Voxel::Space{ .space=solution.at(0), .dims={ dims[0], dims[1], dims[2] } };
|
auto piece_rotations = Voxel::getAllRotations(&space);
|
||||||
auto unique_rots = Voxel::getUniqueRotations(&space);
|
for (int rot_i = 0; rot_i < piece_rotations.size(); rot_i++) {
|
||||||
soln_rotations.insert(soln_rotations.end(), unique_rots.begin(), unique_rots.end());
|
result[rot_i].push_back(piece_rotations[rot_i].space);
|
||||||
}
|
}
|
||||||
for (auto &rotation : soln_rotations) {
|
}
|
||||||
auto end = unique_solns.size();
|
return result;
|
||||||
for (int i = 0; i < end; i++) {
|
}
|
||||||
if (rotation == unique_solns[i]) {
|
|
||||||
foundMatch = true;
|
auto filter_unique(std::vector<SomaSolution> *solutions, int dims[3]) -> std::vector<SomaSolution> {
|
||||||
|
if (solutions->size() == 0) {
|
||||||
|
return std::vector<SomaSolution>();
|
||||||
|
}
|
||||||
|
auto unique_solns = std::vector<SomaSolution>{};
|
||||||
|
for (auto &solution : *solutions) {
|
||||||
|
auto found_match = false;
|
||||||
|
for (auto &rotation : get_solution_rotations(&solution, dims)) {
|
||||||
|
for (auto &unique_soln : unique_solns) {
|
||||||
|
auto is_match = true;
|
||||||
|
for (int piece_i = 0; piece_i < unique_soln.size(); piece_i++) {
|
||||||
|
if (rotation[piece_i] != unique_soln[piece_i]) {
|
||||||
|
is_match = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (is_match) {
|
||||||
|
found_match = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (found_match) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!foundMatch) {
|
if (!found_match) {
|
||||||
unique_solns.push_back(solution);
|
unique_solns.push_back(SomaSolution(solution));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return unique_solns;
|
return unique_solns;
|
||||||
@@ -137,12 +175,12 @@ auto get_reprs_input(int units_required) -> std::vector<uint64_t> {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
auto bit_repr = 0ull;
|
auto bit_repr = 0ul;
|
||||||
auto i = 0;
|
auto i = 0;
|
||||||
auto good_repr = true;
|
auto good_repr = true;
|
||||||
for (auto it = input.rbegin(); it < input.rend(); it++, i++) {
|
for (auto it = input.rbegin(); it < input.rend(); it++, i++) {
|
||||||
if (*it == '1') {
|
if (*it == '1') {
|
||||||
bit_repr |= 1ull << i;
|
bit_repr |= 1ul << i;
|
||||||
total_units++;
|
total_units++;
|
||||||
} else if (*it != '0' || i >= 64) {
|
} else if (*it != '0' || i >= 64) {
|
||||||
std::cout << "Input invalid. Enter a binary string only with max 64 bits." << '\n';
|
std::cout << "Input invalid. Enter a binary string only with max 64 bits." << '\n';
|
||||||
@@ -158,19 +196,21 @@ auto get_reprs_input(int units_required) -> std::vector<uint64_t> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto main() -> int {
|
auto main() -> int {
|
||||||
int dims[3] = { 3, 3, 3 };
|
int dims[3];
|
||||||
//get_dims_input(dims);
|
get_dims_input(dims);
|
||||||
std::cout << '\n';
|
std::cout << '\n';
|
||||||
//auto reprs = get_reprs_input(dims[0]*dims[1]*dims[2]);
|
auto reprs = get_reprs_input(dims[0]*dims[1]*dims[2]);
|
||||||
|
/*
|
||||||
auto reprs = std::vector<uint64_t>{
|
auto reprs = std::vector<uint64_t>{
|
||||||
23ull,
|
23ul,
|
||||||
30ull,
|
30ul,
|
||||||
15ull,
|
15ul,
|
||||||
43ull,
|
1043ul,
|
||||||
172ull,
|
24594ul,
|
||||||
92ull,
|
12306ul,
|
||||||
11ull,
|
11ul,
|
||||||
};
|
};
|
||||||
|
*/
|
||||||
std::cout << "Great. Calculating solutions...\n";
|
std::cout << "Great. Calculating solutions...\n";
|
||||||
|
|
||||||
auto offsets = std::vector<int>();
|
auto offsets = std::vector<int>();
|
||||||
@@ -179,14 +219,16 @@ auto main() -> int {
|
|||||||
|
|
||||||
auto model_space = Voxel::Space{
|
auto model_space = Voxel::Space{
|
||||||
.space={},
|
.space={},
|
||||||
.dims={dims[0], dims[1], dims[2]},
|
.dim_x=dims[0],
|
||||||
|
.dim_y=dims[1],
|
||||||
|
.dim_z=dims[2],
|
||||||
};
|
};
|
||||||
|
|
||||||
offsets.push_back(polycubes.size());
|
offsets.push_back(0);
|
||||||
auto space = model_space;
|
auto space = model_space;
|
||||||
space.space = reprs[0];
|
space.space = reprs[0];
|
||||||
Voxel::cullEmptySpace(&space);
|
Voxel::cullEmptySpace(&space);
|
||||||
auto positions = Voxel::getAllPositionsInPrism(space.space, space.dims, dims);
|
auto positions = Voxel::getAllPositionsInPrism(&space, dims);
|
||||||
polycubes.insert(polycubes.end(), positions.begin(), positions.end());
|
polycubes.insert(polycubes.end(), positions.begin(), positions.end());
|
||||||
|
|
||||||
for (int i = 1; i < reprs.size(); i++) {
|
for (int i = 1; i < reprs.size(); i++) {
|
||||||
@@ -200,8 +242,17 @@ auto main() -> int {
|
|||||||
|
|
||||||
offsets.push_back(polycubes.size());
|
offsets.push_back(polycubes.size());
|
||||||
|
|
||||||
auto solns = backtrack_solve(&polycubes, &offsets);
|
auto solutions = std::vector<SomaSolution>{std::vector<uint64_t>(reprs.size())};
|
||||||
|
auto solver = Solver{
|
||||||
|
.input=&polycubes,
|
||||||
|
.offsets=&offsets,
|
||||||
|
.solutions=&solutions,
|
||||||
|
};
|
||||||
|
|
||||||
std::cout << solns << std::endl;
|
backtrack_solve(&solver);
|
||||||
|
|
||||||
|
auto filtered_solns = filter_unique(solver.solutions, dims);
|
||||||
|
|
||||||
|
std::cout << filtered_solns.size() << std::endl;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
331
tests.cpp
331
tests.cpp
@@ -1,63 +1,312 @@
|
|||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
|
#include <istream>
|
||||||
|
#include <tuple>
|
||||||
#include "VoxelSpace.h"
|
#include "VoxelSpace.h"
|
||||||
|
|
||||||
TEST(VoxelSpaces, BasicPositions) {
|
TEST(VoxelSpaces, BasicPositions) {
|
||||||
auto space = Voxel::Space{ .space=23ull, .dims={3, 3, 3}};
|
auto space = Voxel::Space{
|
||||||
EXPECT_EQ(Voxel::filledAt(space.space, space.dims, 0, 0, 1), true);
|
.space=23ul,
|
||||||
EXPECT_EQ(Voxel::filledAt(space.space, space.dims, 1, 0, 0), false);
|
.dim_x=3,
|
||||||
EXPECT_EQ(Voxel::filledAt(space.space, space.dims, 2, 1, 2), false);
|
.dim_y=3,
|
||||||
EXPECT_EQ(Voxel::filledAt(space.space, space.dims, 1, 2, 1), false);
|
.dim_z=3,
|
||||||
EXPECT_EQ(Voxel::filledAt(space.space, space.dims, 0, 0, 0), true);
|
};
|
||||||
EXPECT_EQ(Voxel::filledAt(space.space, space.dims, 2, 2, 1), false);
|
EXPECT_EQ(Voxel::filledAt(&space, 0, 0, 1), true);
|
||||||
|
EXPECT_EQ(Voxel::filledAt(&space, 1, 0, 0), false);
|
||||||
|
EXPECT_EQ(Voxel::filledAt(&space, 2, 1, 2), false);
|
||||||
|
EXPECT_EQ(Voxel::filledAt(&space, 1, 2, 1), false);
|
||||||
|
EXPECT_EQ(Voxel::filledAt(&space, 0, 0, 0), true);
|
||||||
|
EXPECT_EQ(Voxel::filledAt(&space, 2, 2, 1), false);
|
||||||
|
|
||||||
space = Voxel::Space{ .space=30ull, .dims={3, 3, 3}};
|
space.space = 30ul;
|
||||||
EXPECT_EQ(Voxel::filledAt(space.space, space.dims, 0, 0, 1), true);
|
EXPECT_EQ(Voxel::filledAt(&space, 0, 0, 1), true);
|
||||||
EXPECT_EQ(Voxel::filledAt(space.space, space.dims, 1, 0, 0), false);
|
EXPECT_EQ(Voxel::filledAt(&space, 1, 0, 0), false);
|
||||||
EXPECT_EQ(Voxel::filledAt(space.space, space.dims, 2, 1, 2), false);
|
EXPECT_EQ(Voxel::filledAt(&space, 2, 1, 2), false);
|
||||||
EXPECT_EQ(Voxel::filledAt(space.space, space.dims, 1, 2, 1), false);
|
EXPECT_EQ(Voxel::filledAt(&space, 1, 2, 1), false);
|
||||||
EXPECT_EQ(Voxel::filledAt(space.space, space.dims, 0, 0, 0), false);
|
EXPECT_EQ(Voxel::filledAt(&space, 0, 0, 0), false);
|
||||||
EXPECT_EQ(Voxel::filledAt(space.space, space.dims, 2, 2, 1), false);
|
EXPECT_EQ(Voxel::filledAt(&space, 2, 2, 1), false);
|
||||||
|
|
||||||
space = Voxel::Space{ .space=15ull, .dims={3, 3, 3}};
|
space.space = 15ul;
|
||||||
EXPECT_EQ(Voxel::filledAt(space.space, space.dims, 0, 0, 1), true);
|
EXPECT_EQ(Voxel::filledAt(&space, 0, 0, 1), true);
|
||||||
EXPECT_EQ(Voxel::filledAt(space.space, space.dims, 1, 0, 0), false);
|
EXPECT_EQ(Voxel::filledAt(&space, 1, 0, 0), false);
|
||||||
EXPECT_EQ(Voxel::filledAt(space.space, space.dims, 2, 1, 2), false);
|
EXPECT_EQ(Voxel::filledAt(&space, 2, 1, 2), false);
|
||||||
EXPECT_EQ(Voxel::filledAt(space.space, space.dims, 1, 2, 1), false);
|
EXPECT_EQ(Voxel::filledAt(&space, 1, 2, 1), false);
|
||||||
EXPECT_EQ(Voxel::filledAt(space.space, space.dims, 0, 0, 0), true);
|
EXPECT_EQ(Voxel::filledAt(&space, 0, 0, 0), true);
|
||||||
EXPECT_EQ(Voxel::filledAt(space.space, space.dims, 2, 2, 1), false);
|
EXPECT_EQ(Voxel::filledAt(&space, 2, 2, 1), false);
|
||||||
|
|
||||||
space = Voxel::Space{ .space=23ull, .dims={3, 3, 3}};
|
space.space = 23ul;
|
||||||
EXPECT_EQ(Voxel::filledAt(space.space, space.dims, 0, 0, 1), true);
|
EXPECT_EQ(Voxel::filledAt(&space, 0, 0, 1), true);
|
||||||
EXPECT_EQ(Voxel::filledAt(space.space, space.dims, 1, 0, 0), false);
|
EXPECT_EQ(Voxel::filledAt(&space, 1, 0, 0), false);
|
||||||
EXPECT_EQ(Voxel::filledAt(space.space, space.dims, 2, 1, 2), false);
|
EXPECT_EQ(Voxel::filledAt(&space, 2, 1, 2), false);
|
||||||
EXPECT_EQ(Voxel::filledAt(space.space, space.dims, 1, 2, 1), false);
|
EXPECT_EQ(Voxel::filledAt(&space, 1, 2, 1), false);
|
||||||
EXPECT_EQ(Voxel::filledAt(space.space, space.dims, 0, 0, 0), true);
|
EXPECT_EQ(Voxel::filledAt(&space, 0, 0, 0), true);
|
||||||
EXPECT_EQ(Voxel::filledAt(space.space, space.dims, 2, 2, 1), false);
|
EXPECT_EQ(Voxel::filledAt(&space, 2, 2, 1), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(VoxelSpaces, RotatedIndices) {
|
TEST(VoxelSpaces, RotatedIndices) {
|
||||||
auto space1 = Voxel::Space{ .space=172ull, .dims={3, 3, 3}};
|
auto space1 = Voxel::Space{
|
||||||
|
.space=172ul,
|
||||||
|
.dim_x=3,
|
||||||
|
.dim_y=3,
|
||||||
|
.dim_z=3,
|
||||||
|
};
|
||||||
|
|
||||||
EXPECT_EQ(Voxel::newIndexRotX(space1.dims, 0, 0, 0), 6);
|
EXPECT_EQ(Voxel::newIndexRotX(&space1, 0, 0, 0), 6);
|
||||||
EXPECT_EQ(Voxel::newIndexRotX(space1.dims, 1, 0, 1), 12);
|
EXPECT_EQ(Voxel::newIndexRotX(&space1, 1, 0, 1), 12);
|
||||||
|
|
||||||
EXPECT_EQ(Voxel::newIndexRotY(space1.dims, 0, 1, 0), 5);
|
EXPECT_EQ(Voxel::newIndexRotY(&space1, 0, 1, 0), 5);
|
||||||
EXPECT_EQ(Voxel::newIndexRotY(space1.dims, 1, 2, 0), 7);
|
EXPECT_EQ(Voxel::newIndexRotY(&space1, 1, 2, 0), 7);
|
||||||
|
|
||||||
EXPECT_EQ(Voxel::newIndexRotZ(space1.dims, 1, 0, 2), 23);
|
EXPECT_EQ(Voxel::newIndexRotZ(&space1, 1, 0, 2), 23);
|
||||||
EXPECT_EQ(Voxel::newIndexRotZ(space1.dims, 0, 0, 0), 18);
|
EXPECT_EQ(Voxel::newIndexRotZ(&space1, 0, 0, 0), 18);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(VoxelSpaces, UniqueRotations) {
|
||||||
|
auto space1 = Voxel::Space{
|
||||||
|
.space=30ul,
|
||||||
|
.dim_x=3,
|
||||||
|
.dim_y=3,
|
||||||
|
.dim_z=3,
|
||||||
|
};
|
||||||
|
|
||||||
|
auto rotations = Voxel::getUniqueRotations(&space1);
|
||||||
|
auto expected_rots = std::vector<Voxel::Space>{
|
||||||
|
{ 30ul, 1, 2, 3 },
|
||||||
|
{ 45ul, 1, 3, 2 },
|
||||||
|
{ 30ul, 3, 2, 1 },
|
||||||
|
{ 30ul, 3, 1, 2 },
|
||||||
|
{ 45ul, 3, 2, 1 },
|
||||||
|
{ 45ul, 3, 1, 2 },
|
||||||
|
{ 51ul, 1, 2, 3 },
|
||||||
|
{ 30ul, 1, 3, 2 },
|
||||||
|
{ 30ul, 2, 3, 1 },
|
||||||
|
{ 30ul, 2, 1, 3 },
|
||||||
|
{ 51ul, 2, 3, 1 },
|
||||||
|
{ 51ul, 2, 1, 3 },
|
||||||
|
};
|
||||||
|
|
||||||
|
ASSERT_EQ(expected_rots.size(), rotations.size());
|
||||||
|
|
||||||
|
for (int i = 0; i < rotations.size(); i++) {
|
||||||
|
if (i <= expected_rots.size()) {
|
||||||
|
EXPECT_EQ(Voxel::isMatch(&expected_rots.at(i), &rotations.at(i)), true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(VoxelSpaces, AllPermutationsInPrism) {
|
||||||
|
auto space1 = Voxel::Space{
|
||||||
|
.space=30ul,
|
||||||
|
.dim_x=3,
|
||||||
|
.dim_y=3,
|
||||||
|
.dim_z=3,
|
||||||
|
};
|
||||||
|
|
||||||
|
auto prism_dims = std::array<int, 3>{ 3, 3, 3 };
|
||||||
|
auto perms = Voxel::getAllPermutationsInPrism(&space1, prism_dims.begin());
|
||||||
|
auto expected_perms = std::vector<uint64_t>{
|
||||||
|
30ul,
|
||||||
|
240ul,
|
||||||
|
15360ul,
|
||||||
|
122880ul,
|
||||||
|
7864320ul,
|
||||||
|
62914560ul,
|
||||||
|
153ul,
|
||||||
|
306ul,
|
||||||
|
78336ul,
|
||||||
|
156672ul,
|
||||||
|
40108032ul,
|
||||||
|
80216064ul,
|
||||||
|
266760ul,
|
||||||
|
533520ul,
|
||||||
|
1067040ul,
|
||||||
|
2134080ul,
|
||||||
|
4268160ul,
|
||||||
|
8536320ul,
|
||||||
|
263682ul,
|
||||||
|
527364ul,
|
||||||
|
2109456ul,
|
||||||
|
4218912ul,
|
||||||
|
16875648ul,
|
||||||
|
33751296ul,
|
||||||
|
2101761ul,
|
||||||
|
4203522ul,
|
||||||
|
8407044ul,
|
||||||
|
16814088ul,
|
||||||
|
33628176ul,
|
||||||
|
67256352ul,
|
||||||
|
525825ul,
|
||||||
|
1051650ul,
|
||||||
|
4206600ul,
|
||||||
|
8413200ul,
|
||||||
|
33652800ul,
|
||||||
|
67305600ul,
|
||||||
|
51ul,
|
||||||
|
408ul,
|
||||||
|
26112ul,
|
||||||
|
208896ul,
|
||||||
|
13369344ul,
|
||||||
|
106954752ul,
|
||||||
|
90ul,
|
||||||
|
180ul,
|
||||||
|
46080ul,
|
||||||
|
92160ul,
|
||||||
|
23592960ul,
|
||||||
|
47185920ul,
|
||||||
|
4680ul,
|
||||||
|
9360ul,
|
||||||
|
18720ul,
|
||||||
|
2396160ul,
|
||||||
|
4792320ul,
|
||||||
|
9584640ul,
|
||||||
|
1542ul,
|
||||||
|
12336ul,
|
||||||
|
98688ul,
|
||||||
|
789504ul,
|
||||||
|
6316032ul,
|
||||||
|
50528256ul,
|
||||||
|
36873ul,
|
||||||
|
73746ul,
|
||||||
|
147492ul,
|
||||||
|
18878976ul,
|
||||||
|
37757952ul,
|
||||||
|
75515904ul,
|
||||||
|
3075ul,
|
||||||
|
24600ul,
|
||||||
|
196800ul,
|
||||||
|
1574400ul,
|
||||||
|
12595200ul,
|
||||||
|
100761600ul,
|
||||||
|
};
|
||||||
|
|
||||||
|
ASSERT_EQ(expected_perms.size(), perms.size());
|
||||||
|
|
||||||
|
for (int i = 0; i < perms.size(); i++) {
|
||||||
|
if (i <= expected_perms.size()) {
|
||||||
|
EXPECT_EQ(expected_perms.at(i), perms.at(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(VoxelSpaces, RotateXYZ) {
|
TEST(VoxelSpaces, RotateXYZ) {
|
||||||
auto space1 = Voxel::Space{ .space=30ull, .dims={3, 3, 3}};
|
auto space1 = Voxel::Space{
|
||||||
auto space2 = Voxel::Space{ .space=30ull, .dims={3, 3, 3}};
|
.space=30ul,
|
||||||
auto space3 = Voxel::Space{ .space=30ull, .dims={3, 3, 3}};
|
.dim_x=3,
|
||||||
|
.dim_y=3,
|
||||||
|
.dim_z=3,
|
||||||
|
};
|
||||||
|
|
||||||
|
auto space2 = Voxel::Space{
|
||||||
|
.space=30ul,
|
||||||
|
.dim_x=3,
|
||||||
|
.dim_y=3,
|
||||||
|
.dim_z=3,
|
||||||
|
};
|
||||||
|
|
||||||
|
auto space3 = Voxel::Space{
|
||||||
|
.space=30ul,
|
||||||
|
.dim_x=3,
|
||||||
|
.dim_y=3,
|
||||||
|
.dim_z=3,
|
||||||
|
};
|
||||||
|
|
||||||
Voxel::rotate90X(&space1);
|
Voxel::rotate90X(&space1);
|
||||||
Voxel::rotate90Y(&space2);
|
Voxel::rotate90Y(&space2);
|
||||||
Voxel::rotate90Z(&space3);
|
Voxel::rotate90Z(&space3);
|
||||||
EXPECT_EQ(space1.space, 153ull);
|
EXPECT_EQ(space1.space, 153ul);
|
||||||
EXPECT_EQ(space2.space, 1067040ull);
|
EXPECT_EQ(space2.space, 1067040ul);
|
||||||
EXPECT_EQ(space3.space, 1574400ull);
|
EXPECT_EQ(space3.space, 1574400ul);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(VoxelSpaces, GetAllPositionsInPrism) {
|
||||||
|
int dims[] = {3, 3, 3};
|
||||||
|
|
||||||
|
auto space1 = Voxel::Space{
|
||||||
|
.space=30ul,
|
||||||
|
.dim_x=3,
|
||||||
|
.dim_y=3,
|
||||||
|
.dim_z=3,
|
||||||
|
};
|
||||||
|
Voxel::cullEmptySpace(&space1);
|
||||||
|
uint64_t expected_results1[] = {
|
||||||
|
30ul,
|
||||||
|
240ul,
|
||||||
|
15360ul,
|
||||||
|
122880ul,
|
||||||
|
7864320ul,
|
||||||
|
62914560ul,
|
||||||
|
};
|
||||||
|
|
||||||
|
auto space2 = Voxel::Space{
|
||||||
|
.space=23ul,
|
||||||
|
.dim_x=3,
|
||||||
|
.dim_y=3,
|
||||||
|
.dim_z=3,
|
||||||
|
};
|
||||||
|
Voxel::cullEmptySpace(&space2);
|
||||||
|
uint64_t expected_results2[] = {
|
||||||
|
23ul,
|
||||||
|
184ul,
|
||||||
|
11776ul,
|
||||||
|
94208ul,
|
||||||
|
6029312ul,
|
||||||
|
48234496ul,
|
||||||
|
};
|
||||||
|
|
||||||
|
auto space3 = Voxel::Space{
|
||||||
|
.space=15ul,
|
||||||
|
.dim_x=3,
|
||||||
|
.dim_y=3,
|
||||||
|
.dim_z=3,
|
||||||
|
};
|
||||||
|
Voxel::cullEmptySpace(&space3);
|
||||||
|
uint64_t expected_results3[] = {
|
||||||
|
15ul,
|
||||||
|
120ul,
|
||||||
|
7680ul,
|
||||||
|
61440ul,
|
||||||
|
3932160ul,
|
||||||
|
31457280ul,
|
||||||
|
};
|
||||||
|
|
||||||
|
auto positions1 = Voxel::getAllPositionsInPrism(&space1, dims);
|
||||||
|
auto positions2 = Voxel::getAllPositionsInPrism(&space2, dims);
|
||||||
|
auto positions3 = Voxel::getAllPositionsInPrism(&space3, dims);
|
||||||
|
auto mismatches1 = std::vector<std::tuple<int, uint64_t, uint64_t>>();
|
||||||
|
auto mismatches2 = std::vector<std::tuple<int, uint64_t, uint64_t>>();
|
||||||
|
auto mismatches3 = std::vector<std::tuple<int, uint64_t, uint64_t>>();
|
||||||
|
|
||||||
|
for (int i = 0; i < 6; i++) {
|
||||||
|
if (positions1[i] != expected_results1[i]) {
|
||||||
|
mismatches1.push_back({ i, positions1[i], expected_results1[i] });
|
||||||
|
}
|
||||||
|
if (positions2[i] != expected_results2[i]) {
|
||||||
|
mismatches2.push_back({ i, positions2[i], expected_results2[i] });
|
||||||
|
}
|
||||||
|
if (positions3[i] != expected_results3[i]) {
|
||||||
|
mismatches3.push_back({ i, positions3[i], expected_results3[i] });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EXPECT_EQ(mismatches1.size(), 0);
|
||||||
|
if (mismatches1.size() > 0) {
|
||||||
|
std::cout << "Index - Actual - Expected" << std::endl;
|
||||||
|
for (auto &mismatch : mismatches1) {
|
||||||
|
std::cout << std::get<0>(mismatch) << " - " << std::get<1>(mismatch) << " - " << std::get<2>(mismatch) << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EXPECT_EQ(mismatches2.size(), 0);
|
||||||
|
if (mismatches2.size() > 0) {
|
||||||
|
std::cout << "Index - Actual - Expected" << std::endl;
|
||||||
|
for (auto &mismatch : mismatches2) {
|
||||||
|
std::cout << std::get<0>(mismatch) << " - " << std::get<1>(mismatch) << " - " << std::get<2>(mismatch) << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EXPECT_EQ(mismatches3.size(), 0);
|
||||||
|
if (mismatches3.size() > 0) {
|
||||||
|
std::cout << "Index - Actual - Expected" << std::endl;
|
||||||
|
for (auto &mismatch : mismatches3) {
|
||||||
|
std::cout << "At " << std::get<0>(mismatch) << ": " << std::get<1>(mismatch) << " != " << std::get<2>(mismatch) << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user