Last active
July 5, 2021 11:37
-
-
Save popey456963/470d995032d321b6e49100c51d65f249 to your computer and use it in GitHub Desktop.
Making Cubes
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
# requires the following libraries: | |
# - numpy-stl | |
# - numpy | |
# - matplotlib | |
# run as: | |
# python main.py | |
# matplotlib requires a window system available | |
from stl import mesh | |
import stl | |
import math | |
import numpy | |
from make_cube import make_cube, make_cube_2 | |
layout = [ | |
[True, False], | |
[True, True] | |
] | |
# layout = [ | |
# [True, False, False], | |
# [True, True, False], | |
# [True, False, False] | |
# ] | |
layout = [ | |
[True, True, True, True], | |
[True, False, False, True], | |
[True, False, False, True], | |
[True, True, True, True] | |
] | |
def get(l, i): | |
if i < 0 or i >= len(l): | |
return None | |
return l[i] | |
def get_md(l, j, i): | |
if j < 0 or j >= len(l): | |
return None | |
return get(l[j], i) | |
orthogonal_adjacents = [(0, -1), (0, 1), (-1, 0), (1, 0)] | |
intersections = [] | |
for y in range(len(layout)): | |
for x in range(len(layout[y])): | |
if layout[y][x]: | |
for delta in orthogonal_adjacents: | |
other_cube = (delta[0] + x, delta[1] + y) | |
if other_cube[1] < 0 or other_cube[1] >= len(layout) or other_cube[0] < 0 or other_cube[0] >= len(layout[y]): | |
continue | |
if not layout[other_cube[1]][other_cube[0]]: | |
continue | |
direction = 'ROW' if delta[0] == 0 else 'COLUMN' | |
intersections.append(((x, y), (other_cube[0], other_cube[1]), direction)) | |
def is_equal(a, b): | |
return (a[0] == b[0] and a[1] == b[1]) or (a[0] == b[1] and b[0] == a[1]) | |
unique_intersections = [] | |
for i, a in enumerate(intersections): | |
if not any(is_equal(a, b) for b in intersections[:i]): | |
unique_intersections.append(a) | |
print(unique_intersections) | |
count = int(len(intersections) / 2) | |
cubes = sum(sum(x) for x in layout) | |
data = make_cube() | |
data_2 = make_cube() | |
cube_size = 25.6 | |
connector_width = 0.7 | |
connector_depth = 0.5 | |
data['vectors'] *= cube_size | |
meshes = [mesh.Mesh(data.copy()) for _ in range(cubes)] | |
joining_meshes = [mesh.Mesh(data_2.copy()) for _ in range(count)] | |
for i, _ in enumerate(joining_meshes): | |
item = unique_intersections[i] | |
if item[2] == 'ROW': | |
# these affect the size of the box | |
joining_meshes[i].y *= cube_size - (connector_depth * 2) | |
joining_meshes[i].z *= cube_size - (connector_depth * 2) | |
joining_meshes[i].x *= connector_width | |
# these affect it's offset from the center point | |
joining_meshes[i].y += ((cube_size + connector_width) * max(item[0][0], item[1][0])) + connector_depth | |
joining_meshes[i].x += ((cube_size + connector_width) * max(item[0][1], item[1][1])) - connector_width | |
if item[2] == 'COLUMN': | |
# these affect the size of the box | |
joining_meshes[i].x *= cube_size - (connector_depth * 2) | |
joining_meshes[i].y *= connector_width | |
joining_meshes[i].z *= cube_size - (connector_depth * 2) | |
# these affect it's offset from the center point | |
joining_meshes[i].y += ((cube_size + connector_width) * max(item[0][0], item[1][0])) - connector_width | |
joining_meshes[i].x += ((cube_size + connector_width) * max(item[0][1], item[1][1])) + connector_depth | |
# we want the joining meshes to be half a mm | |
joining_meshes[i].z += connector_depth | |
cur_cube = 0 | |
for row_idx, row in enumerate(layout): | |
for column_idx, item in enumerate(row): | |
if item: | |
meshes[cur_cube].x += (cube_size + connector_width) * row_idx | |
meshes[cur_cube].y += (cube_size + connector_width) * column_idx | |
cur_cube += 1 | |
# Optionally render the rotated cube faces | |
from matplotlib import pyplot | |
from mpl_toolkits import mplot3d | |
# Create a new plot | |
figure = pyplot.figure() | |
axes = mplot3d.Axes3D(figure) | |
# Render the cube faces | |
for m in meshes: | |
axes.add_collection3d(mplot3d.art3d.Poly3DCollection(m.vectors)) | |
for m in joining_meshes: | |
axes.add_collection3d(mplot3d.art3d.Poly3DCollection(m.vectors)) | |
# Auto scale to the mesh size | |
scale = numpy.concatenate([m.points for m in meshes]).flatten() | |
axes.auto_scale_xyz(scale, scale, scale) | |
combined = mesh.Mesh(numpy.concatenate([copy.data for copy in meshes] + [a.data for a in joining_meshes])) | |
combined.save('cube.stl', mode=stl.Mode.ASCII) | |
# mesh.Mesh(scale).save('cube.stl') | |
# Show the plot to the screen | |
pyplot.show() |
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
import numpy | |
from stl import mesh | |
def make_cube(): | |
# Create 3 faces of a cube | |
data = numpy.zeros(12, dtype=mesh.Mesh.dtype) | |
# Top of the cube | |
data['vectors'][0] = numpy.array([[0, 1, 1], | |
[1, 0, 1], | |
[0, 0, 1]]) | |
data['vectors'][1] = numpy.array([[1, 0, 1], | |
[0, 1, 1], | |
[1, 1, 1]]) | |
# Front face | |
data['vectors'][2] = numpy.array([[1, 0, 0], | |
[1, 0, 1], | |
[1, 1, 0]]) | |
data['vectors'][3] = numpy.array([[1, 1, 1], | |
[1, 0, 1], | |
[1, 1, 0]]) | |
# Left face | |
data['vectors'][4] = numpy.array([[0, 0, 0], | |
[1, 0, 0], | |
[1, 0, 1]]) | |
data['vectors'][5] = numpy.array([[0, 0, 0], | |
[0, 0, 1], | |
[1, 0, 1]]) | |
# Top of the cube | |
data['vectors'][6] = numpy.array([[0, 1, 0], | |
[1, 0, 0], | |
[0, 0, 0]]) | |
data['vectors'][7] = numpy.array([[1, 0, 0], | |
[0, 1, 0], | |
[1, 1, 0]]) | |
# Front face | |
data['vectors'][8] = numpy.array([[0, 0, 0], | |
[0, 0, 1], | |
[0, 1, 0]]) | |
data['vectors'][9] = numpy.array([[0, 1, 1], | |
[0, 0, 1], | |
[0, 1, 0]]) | |
# Left face | |
data['vectors'][10] = numpy.array([[0, 1, 0], | |
[1, 1, 0], | |
[1, 1, 1]]) | |
data['vectors'][11] = numpy.array([[0, 1, 0], | |
[0, 1, 1], | |
[1, 1, 1]]) | |
return data | |
def make_cube_2(): | |
# Create 3 faces of a cube | |
data2 = numpy.zeros(8, dtype=mesh.Mesh.dtype) | |
# Top of the cube | |
data2['vectors'][0] = numpy.array([[0, 1, 1], | |
[1, 0, 1], | |
[0, 0, 1]]) | |
data2['vectors'][1] = numpy.array([[1, 0, 1], | |
[0, 1, 1], | |
[1, 1, 1]]) | |
# Left face | |
data2['vectors'][2] = numpy.array([[0, 0, 0], | |
[1, 0, 0], | |
[1, 0, 1]]) | |
data2['vectors'][3] = numpy.array([[0, 0, 0], | |
[0, 0, 1], | |
[1, 0, 1]]) | |
# Top of the cube | |
data2['vectors'][4] = numpy.array([[0, 1, 0], | |
[1, 0, 0], | |
[0, 0, 0]]) | |
data2['vectors'][5] = numpy.array([[1, 0, 0], | |
[0, 1, 0], | |
[1, 1, 0]]) | |
# Left face | |
data2['vectors'][6] = numpy.array([[0, 1, 0], | |
[1, 1, 0], | |
[1, 1, 1]]) | |
data2['vectors'][7] = numpy.array([[0, 1, 0], | |
[0, 1, 1], | |
[1, 1, 1]]) | |
return data2 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment