Skip to content

Commit

Permalink
Reducing rotations based on bounding box constraint
Browse files Browse the repository at this point in the history
  • Loading branch information
amal committed Aug 23, 2023
1 parent 7e05d7a commit aaf49b5
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 13 deletions.
29 changes: 25 additions & 4 deletions python/cubes.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from libraries.resizing import expand_cube
from libraries.packing import pack, unpack
from libraries.renderer import render_shapes
from libraries.rotation import all_rotations
from libraries.rotation import all_rotations, one_diff_rot, all_diff_rot


def log_if_needed(n, total_n):
Expand Down Expand Up @@ -87,11 +87,32 @@ def get_canonical_packing(polycube: np.ndarray,
"""
max_id = b'\x00'
for cube_rotation in all_rotations(polycube):
shape = polycube.shape

if shape[0] == shape[1] == shape[2]:
for cube_rotation in all_rotations(polycube):
this_id = pack(cube_rotation)
if this_id in known_ids:
return this_id
if this_id > max_id:
max_id = this_id
return max_id

for idx in range(0, 3):
if shape[idx] == shape[(idx + 1) % 3]:
for cube_rotation in one_diff_rot(polycube, (idx + 2) % 3, [idx, (idx + 1) % 3]):
this_id = pack(cube_rotation)
if this_id in known_ids:
return this_id
if this_id > max_id:
max_id = this_id
return max_id

for cube_rotation in all_diff_rot(polycube):
this_id = pack(cube_rotation)
if (this_id in known_ids):
if this_id in known_ids:
return this_id
if (this_id > max_id):
if this_id > max_id:
max_id = this_id
return max_id

Expand Down
64 changes: 56 additions & 8 deletions python/libraries/resizing.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import numpy as np
from typing import Generator

import numpy as np


def crop_cube(cube: np.ndarray) -> np.ndarray:
"""
Expand All @@ -23,6 +24,53 @@ def crop_cube(cube: np.ndarray) -> np.ndarray:
return cube


def fix_axis(cube):
"""
Rotate cube to make boundary sizes in sorted order.
Ex : if input cube.shape = (4, 1, 2) this method rotate it to be (1, 2, 4)
Parameters:
cube (np.array): 3D Numpy byte array where 1 values indicate polycube positions
Returns:
np.array: Cropped 3D Numpy byte array equivalent to cube, but with no zero padding
"""
if cube.shape == tuple(sorted(cube.shape, reverse=True)):
return cube

if cube.shape == tuple(sorted(cube.shape)):
return np.rot90(cube, 1, (0, 2))

if cube.shape[0] < cube.shape[2] < cube.shape[1]:
return np.rot90(np.rot90(cube, 1, (0, 2)), 1, (1, 2))

if cube.shape[0] == cube.shape[2]:
if cube.shape[0] < cube.shape[1]:
return np.rot90(cube, 1, (0, 1))
else:
return np.rot90(cube, 1, (1, 2))

if cube.shape[0] == cube.shape[1] or cube.shape[1] == cube.shape[2]:
if cube.shape[0] < cube.shape[2]:
return cube
else:
return np.rot90(cube, 1, (0, 2))

if cube.shape[2] < cube.shape[0] < cube.shape[1]:
return np.rot90(cube, 1, (0, 1))

if cube.shape[1] < cube.shape[0] < cube.shape[2]:
return np.rot90(np.rot90(cube, 1, (0, 1)), 1, (1, 2))

if cube.shape[1] < cube.shape[2] < cube.shape[0]:
return np.rot90(cube, 1, (2, 1))

print("error", cube.shape)
exit(2)


def expand_cube(cube: np.ndarray) -> Generator[np.ndarray, None, None]:
"""
Expands a polycube by adding single blocks at all valid locations.
Expand All @@ -41,16 +89,16 @@ def expand_cube(cube: np.ndarray) -> Generator[np.ndarray, None, None]:
output_cube = np.array(cube)

xs, ys, zs = cube.nonzero()
output_cube[xs+1, ys, zs] = 1
output_cube[xs-1, ys, zs] = 1
output_cube[xs, ys+1, zs] = 1
output_cube[xs, ys-1, zs] = 1
output_cube[xs, ys, zs+1] = 1
output_cube[xs, ys, zs-1] = 1
output_cube[xs + 1, ys, zs] = 1
output_cube[xs - 1, ys, zs] = 1
output_cube[xs, ys + 1, zs] = 1
output_cube[xs, ys - 1, zs] = 1
output_cube[xs, ys, zs + 1] = 1
output_cube[xs, ys, zs - 1] = 1

exp = (output_cube ^ cube).nonzero()

for (x, y, z) in zip(exp[0], exp[1], exp[2]):
new_cube = np.array(cube)
new_cube[x, y, z] = 1
yield crop_cube(new_cube)
yield fix_axis(crop_cube(new_cube))
46 changes: 45 additions & 1 deletion python/libraries/rotation.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

def all_rotations(polycube: np.ndarray) -> Generator[np.ndarray, None, None]:
"""
Calculates all rotations of a polycube.
Calculates rotations of a polycube when bounding box size in all axes are equal(Ex (3, 3, 3)).
Adapted from https://stackoverflow.com/questions/33190042/how-to-calculate-all-24-rotations-of-3d-array.
This function computes all 24 rotations around each of the axis x,y,z. It uses numpy operations to do this, to avoid unecessary copies.
Expand Down Expand Up @@ -36,3 +36,47 @@ def single_axis_rotation(polycube, axes):
# rotate about axis 2, 8 rotations about axis 1
yield from single_axis_rotation(np.rot90(polycube, axes=(0, 1)), (0, 2))
yield from single_axis_rotation(np.rot90(polycube, -1, axes=(0, 1)), (0, 2))


def one_diff_rot(cube, diff_axis, equal_axes):
"""
Calculates rotations of a polycube when bounding box size in two axes are equal, but one is different. (Ex (2, 2, 3)).
Only 8 rotations can be done without breaking the bounding box.
Parameters:
polycube (np.array): 3D Numpy byte array where 1 values indicate polycube positions
diff_axis (integer): Axis which has different size
equal_axes (integer array): Axes which have same size
Returns:
generator(np.array): Yields new rotations of this cube about all axes
"""
for _ in range(0, 4):
yield cube
cube = np.rot90(cube, 1, equal_axes)

cube = np.rot90(cube, 2, (diff_axis, equal_axes[0]))

for _ in range(0, 4):
yield cube
cube = np.rot90(cube, 1, equal_axes)


def all_diff_rot(cube):
"""
Calculates rotations of a polycube when bounding box size in all axes are different. (Ex (1, 4, 6)).
Only 4 rotations can be done without breaking the bounding box.
Parameters:
polycube (np.array): 3D Numpy byte array where 1 values indicate polycube positions
Returns:
generator(np.array): Yields new rotations of this cube about all axes
"""
yield cube
yield np.rot90(cube, 2, (0, 1))
yield np.rot90(cube, 2, (0, 2))
yield np.rot90(cube, 2, (1, 2))

0 comments on commit aaf49b5

Please sign in to comment.