Skip to content

Ideas/suggestions #2

@jwhendy

Description

@jwhendy

This is awesome. I've been able to use it successfully to convert a picture of the 2024 eclipse into an stl I can import to Fusion360. Hoping to machine it out, ebonize the wood, pour in translucent epoxy, then machine flat and obtain a cool gradient look.

Anyway, had some thoughts as I wrapped my head around the code.

  • what about adjusting parameters to be more objective vs. relative? reduction_factor and scale work, but I wasn't able to figure out what values to use except by trial and error. I could envision providing a scaled image dimensions instead, or having scale be the output object dimensions in mm.

  • super minor, but I think you can get away with this instead of the use of baselayer_height and subtracting 1 from num_layers. Also, right=True for digitize seemed to work better than right=False (default) and subtracting 1 from the height map result.

# Discretize the height map
discrete_heights = np.linspace(layer_height, layer_height * num_levels, num_levels)
height_map = np.digitize(img, bins=np.linspace(0, 1, num_levels), right=True)
height_map = discrete_heights[height_map]
  • I also used this, and didn't get any errors or issues... is there a reason to do range(0, height-1, 1) instead?
# Create the faces array
faces = []
for y in range(height):
    for x in range(width):
  • I noticed for every bottom face, you were connecting to a vertex at the lowest height. As this is primarily for 3d printing, maybe that's correct? For me, it seemed unintuitive why to do this. I changed it to this, which gives us a flat back at z=0 vs. at z=layer_height
# Bottom face (base of the lithophane)
v0_b = [v0[0], v0[1], 0]
v1_b = [v1[0], v1[1], 0]
v2_b = [v2[0], v2[1], 0]
v3_b = [v3[0], v3[1], 0]
  • lastly, I wanted my stl high res for a nice smooth gradient, so I'm currently using 100 levels. This slows things down quite a bit. If I'm not mistaken, I believe you are adding sides to every single set of vertices internally? I'm not sure how things would behave with 3d printing, but I had success commenting that bit out, and then adding 8 faces just to the perimeter (2 triangles per side). I also added an argument so one could specify to "fill" (internal sides, use your existing code) or not (just add exterior sides to complete the shell)
# Add side faces around perimeter if internal faces not created
if not filled:
    tl = vertices[0, 0]
    tr = vertices[0, width - 1]
    bl = vertices[height-1, 0]
    br = vertices[height-1, width - 1]
    faces.append([tl, bl, [bl[0], bl[1], 0]])
    faces.append([tl, [tl[0], tl[1], 0], [bl[0], bl[1], 0]])
    faces.append([tl, tr, [tr[0], tr[1], 0]])
    faces.append([tl, [tr[0], tr[1], 0], [tl[0], tl[1], 0]])
    faces.append([tr, br, [br[0], br[1], 0]])
    faces.append([tr, [br[0], br[1], 0], [tr[0], tr[1], 0]])
    faces.append([br, bl, [bl[0], bl[1], 0]])
    faces.append([br, [bl[0], bl[1], 0], [br[0], br[1], 0]])

If any of this is useful, I can do a PR. Happy to putz on some other ideas above, like how to scale to a set size. This would be awesome for my purposes. My image is 900px, so I get a 900mm image (I'm using reduction_factor=scale=1) and then scale to my target of 6x6in.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions