22import math
33
44
5- def pack (polycube : np .ndarray ) -> int :
5+ def pack (polycube : np .ndarray ) -> bytes :
66 """
7- Converts a 3D ndarray into a single unsigned integer for quick hashing and efficient storage
8-
9- Converts a {0,1} nd array into a single unique large integer
7+ Converts a 3D ndarray into a single bytes object that unique identifies
8+ the polycube, is hashable, comparable, and allows to reconstruct the
9+ original polycube ndarray.
1010
1111 Parameters:
12- polycube (np.array): 3D Numpy byte array where 1 values indicate polycube positions
12+ polycube (np.array): 3D Numpy byte array where 1 values indicate polycube positions,
13+ and 0 values indicate empty space. Must be of type np.int8.
1314
1415 Returns:
15- int : a unique integer hash
16+ cube_id (bytes) : a bytes representation of the polycube
1617
1718 """
1819
20+ # # Previous implementation:
1921 # pack_cube = np.packbits(polycube.flatten(), bitorder='big')
2022 # cube_hash = 0
2123 # for index in polycube.shape:
@@ -24,31 +26,34 @@ def pack(polycube: np.ndarray) -> int:
2426 # cube_hash = (cube_hash << 8) + int(part)
2527 # return cube_hash
2628
27- data = polycube .tobytes () + polycube .shape [0 ].to_bytes (1 , 'big' ) + polycube .shape [1 ].to_bytes (1 , 'big' ) + polycube .shape [2 ].to_bytes (1 , 'big' )
28- return int .from_bytes (data , 'big' )
29+ # # dtype should be np.int8: (commented out for efficiency)
30+ # if polycube.dtype != np.int8:
31+ # raise TypeError("Polycube must be of type np.int8")
2932
33+ # pack cube
34+ data = polycube .tobytes () + polycube .shape [0 ].to_bytes (1 , 'big' ) \
35+ + polycube .shape [1 ].to_bytes (1 , 'big' ) \
36+ + polycube .shape [2 ].to_bytes (1 , 'big' )
37+ return data
3038
31- def unpack (cube_hash : int ) -> np .ndarray :
32- """
33- Converts a single integer back into a 3D ndarray
3439
40+ def unpack (cube_id : bytes ) -> np .ndarray :
41+ """
42+ Converts a bytes object back into a 3D ndarray
3543
3644 Parameters:
37- cube_hash (int ): a unique integer hash
45+ cube_id (bytes ): a unique bytes object
3846
3947 Returns:
40- np.array: 3D Numpy byte array where 1 values indicate polycube positions
41-
48+ polycube (np.array): 3D Numpy byte array where 1 values indicate
49+ cube positions
50+
4251 """
52+ # Extract shape information
53+ shape = (cube_id [- 3 ], cube_id [- 2 ], cube_id [- 1 ])
54+
55+ # Create ndarray from byte data
56+ polycube = np .frombuffer (cube_id [:- 3 ], dtype = np .int8 )
57+ polycube = polycube .reshape (shape )
58+ return polycube
4359
44- length = math .ceil (math .log2 (cube_hash ))
45- parts = cube_hash .to_bytes (length , byteorder = 'big' )
46- shape = (
47- parts [- 3 ],
48- parts [- 2 ],
49- parts [- 1 ],
50- )
51- size = shape [0 ] * shape [1 ] * shape [2 ]
52- raw = np .frombuffer (parts [:- 3 ], dtype = np .uint8 )
53- final = raw [(len (raw ) - size ):len (raw )].reshape (shape )
54- return final
0 commit comments