5

I am working on a piece of python code that will take in an image in grey scale, scale it, and output a 3d model with the height of each pixel being determined by the value of the grey scale. I have everything working except the output of the 3d model. I am using numpy-stl to create it based on an array of values derived from the image. Using the numpy-stl library I create a box and then copy it as many times as i need for the image. then I translate each one to the position and height corresponding with the image. This all works. The problem comes when I try to save it all as one .stl file. I cant figure out how to combine all the individual meshes of the cubes into one.

Here is just the code dealing with the creation of the 3d array. I can plot the created meshes but not save them.

from stl import mesh
import math
import numpy

test = [[1,2],[2,1]]

a = [[1,2,3,4],
        [5,6,7,8],
        [9,10,11,12],
        [13,14,15,16]]


# Create 6 faces of a cube, 2 triagles per face
data = numpy.zeros(12, dtype=mesh.Mesh.dtype)
#cube defined in stl format 
# 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]])
# Right 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]])
# Bottem 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]])
# Right back
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 back 
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]])


# Generate 4 different meshes so we can rotate them later
meshes = [mesh.Mesh(data.copy()) for _ in range(16)]

#iterates through the array and translates cube in the x and y direction according 
#to position in array and in the z direction according to eh value stored in the array
def ArrayToSTL(array, STLmesh):
  y_count = 0
  x_count = 0
  count = 0
  for row in array:
    x_count = 0
    for item in row:
      meshes[count].x += x_count
      meshes[count].y += y_count
      meshes[count].z += item
      x_count +=1
      count += 1
    y_count += 1

ArrayToSTL(a, meshes)



# 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))

# Auto scale to the mesh size
scale = numpy.concatenate([m.points for m in meshes]).flatten(-1)
axes.auto_scale_xyz(scale, scale, scale)

# Show the plot to the screen
pyplot.show()
Jared Perkins
  • 51
  • 1
  • 4

1 Answers1

0

This works well:

import numpy as np
import stl
from stl import mesh
import os

def combined_stl(meshes, save_path="./combined.stl"):
    combined = mesh.Mesh(np.concatenate([m.data for m in meshes]))
    combined.save(save_path, mode=stl.Mode.ASCII)

loading stored stl files and meshing them, use this.

direc = "path_of_directory"
paths = [os.path.join(direc, i) for i in os.listdir(direc)]
meshes = [mesh.Mesh.from_file(path) for path in paths]
combined_stl(meshes)
Tanay Agrawal
  • 392
  • 1
  • 9
  • I am sure you can save facets of multiple meshes in one STL, but how many software are able to properly read this? Just imagine two meshes sharing the same values for few edges/triangles: it can be exponentially CPU consuming to make them 2 solids again (NP-complete problem?). IMHO, it's best to make the union-boolean operation of the two meshes and save that (althrough potentially not two meshes anymore). – Adrian Maire Jan 06 '23 at 09:25