3D printing Lego sieves

Once you’ve washed these pounds of newly acquired Lego bricks, sorting them is in order. If you’re sorting by shape, one simple method is to use sieves. The main issue with that is finding the right sieve, Lego pieces are precisely calibrated and a sieve that’s slightly off will keep a lot of pieces together. Same if the holes are square rather than round, the pieces won’t separate properly.

Thanks to the development of 3D printing, you don’t need to hunt the store to find the sieve with the exact size. You can design the sieve with the desired hole size and 3D print it yourself. 3D design can be time consuming, but thankfully for something like a sieve, a lot can be automated.

By combining OpenSCAD and SolidPython, a few lines of code can quickly generate a reasonable sieve. Best, it just take one number change to generate a sieve with slightly bigger or smaller holes.


Here is the full python code used to generate this file (also available on github):

import math
from solid import *
from solid.utils import *

# General parameter of the sieves (mm)

# holes diameter
hole_diam = 18
# distance between holes
sep = 1.25

# other parameters that will probably not change
output_file = 'sieve_%d.scad' % hole_diam
box_size = 190
box_thickness = 5
box_height = 40

# hole radius
hr = hole_diam / 2.

# hole spacing x
hspx = hole_diam * sep
# hole spacing y
hspy = hole_diam * sep * sqrt(3.)/2.

base = difference()(
    translate([-box_size/2. + box_thickness, -box_size/2. + box_thickness, -box_height/2.])(
            cube([box_size-2.*box_thickness, box_size-2.*box_thickness, box_height/2.]),
            cylinder(r=5, h=box_height/2.))),
    translate([0, 0, box_thickness])(
        cube([box_size - 2. * box_thickness,
              box_size - 2. * box_thickness,
              box_height], center=True)

# sieve pile up
cw = box_size/2. - box_thickness*3/4.
bottom_guides = (translate([cw, cw,-box_height/2.])(sphere(2.)) +
                 translate([cw, -cw,-box_height/2.])(sphere(2.)) +
                 translate([-cw, cw,-box_height/2.])(sphere(2.)) +
                 translate([-cw, -cw,-box_height/2.])(sphere(2.)))
top_guides = (translate([cw, cw, box_height/2.])(sphere(1.5)) +
              translate([cw, -cw, box_height/2.])(sphere(1.5)) +
              translate([-cw, cw, box_height/2.])(sphere(1.5)) +
              translate([-cw, -cw, box_height/2.])(sphere(1.5)))

# odd lines holes
x_range = int(math.floor((box_size / 2. - box_thickness - hr) / hspx))
y_range = int(math.floor((box_size / 2. - box_thickness - hr) / hspy / 2.))

l =[]
for i in range(-x_range, x_range + 1):
    for j in range(-y_range, y_range + 1):
        l.append(translate([i*hspx, j*hspy*2., 0])(
            cylinder(r=hr, h=100, center=True))

# even lines holes
x_range = int(math.floor((box_size / 2. - box_thickness) / hspx))
y_range = int(math.floor((box_size / 2. - box_thickness) / hspy / 2.))

l2 = []
for i in range(-x_range, x_range):
    for j in range(-y_range, y_range):
        l2.append(translate([(i + 1/2.)*hspx, (2.*j + 1)*hspy, 0])(
                cylinder(r=hr, h=100, center=True))

d = base - l - l2 - bottom_guides + top_guides

scad_render_to_file(d, output_file)

And here is the stl file: http://www.thingiverse.com/thing:1396351

So far, I’ve used a combination of 3 sieves: 18 mm, 14 mm and 10 mm. The process is pretty simple (and quite fast). Start with the biggest sieve, put the pieces in, shake to separate into 2 groups (above and below). Once you’re done, take the below group and put it through the process for the smaller sieve. You can also pile up the sieves (smallest at the bottom) to do everything in one pass.

Here is an example of how the brick get separated:

  • Below 18mm, above 14mm: the 2×2 bricks don’t go through the 18 mm, but the 2×2 plates will. We’ll get most of the 2×1 bricks here as well.
  • sieve_18mm

  • Below 14mm, above 10mm: A lot of the 3×2 plates, the cheese slopes are just slightly too big to go through the 10 mm holes and will stay there.
  • sieve_14mm

  • Below 10mm: the 1×1 plates (round and square), the 1×1 bricks (only the round one and a lot of technic pins.
  • sieve_10mm

Of course, the process in not 100 percent accurate: for example it’s possible for a long technic axle to go all the way down if it comes up in the right position. But in practice, it does work well: in the 10 mm group, it’s mostly axle-3 and some axle-4.

The economics of sorting (part 1)

To sort, or not to sort, that is the question…

Starting with the first lego set, there are no questions: just build it, dismantle it, throw all the pieces in a box, build something else. Then the second set comes. And the third. And so on. At some point, the question inevitably arises: maybe I should sort all these bricks?

But how? Here again, the evolution is fairly well established: first by set, then by color, then by shape and finally by shape and color. These leading to endless discussions about the best sorting method without even going into the details: do you keep the light gray and the light bluish gray pieces together? do you mix the 2×3 plates with the 2×4?

Finding the optimal sorting method

There’s no accounting for taste, but is there a method that’s more efficient? Looking at these images, it’s fairly obvious that there is a difference:


The dark green 2×4 will be more easily spotted in the first picture vs the second.

But is there an absolutely best sorting method? Let’s see a few intuitive examples.

Small collections

If the collections of Lego pieces is only 100 pieces, it does not seem that sorting will provide a huge gain. So the best solution here is to keep them all unsorted.

Big collections with small retrieval

If there are 10 thousands of pieces but you’re looking for a single one, not sorting is probably optimal. Think about going to a Lego flea market, looking for a specific piece, you’re not going to start by sorting the vendor collection before looking for the piece you want.

Big collection with predicted retrieval order

If the collection is big, but you know roughly the order in which the pieces are needed, you can sort them according to this order. For example, if you have 2000 pieces needed to build the temple of Airjitzu in about 200 steps, it makes sense to split these pieces in piles of 100-150 pieces each.

Note that this case is exactly what TLG is doing with the new sets. The temple of Airjitzu pieces were split into 14 bags according to the build order.

Big collection with large unpredicted retrieval

That probably what most people have in mind when considering sorting. There are a lot of pieces, but you don’t know when or how they will be needed.

From these examples, it should be clear that there is no optimal sorting per se. It depends on several factors, at least the size of the collection and the number of pieces retrieved.

Short term vs long term

Deciding to sort the collection is an optimization problem. Spending some time now to gain more later. But as with all these long term investment, as human we tend to be pretty bad and value the short term much more than the long term. In other words, we sort too little, too late.

In the next part, we’ll see how to model this problem. To be continued…


Generating labels for Lego drawers

tl;dr: use the script below to generate thousands of labels.

Once the number of drawers for sorting Lego bricks increases, it becomes necessary to label them properly. I wanted a simple label with a clean representation of the type of brick inside. On this site, there is a script available to generate labels targeted at some specific label printers. However this was really targeted for the label printer and to run on Windows computer. I needed something to run on linux (Debian in my case) and to generate just simple images.

Parts library: LDraw

First you need the models for the lego parts library:

sudo apt-get install ldraw-parts

All the files as .dat are installed under /usr/share/ldraw/parts

Renderer: LDView

Then you need the ldview renderer. You can install one of the package available on the  ldview site (4.3 worked for me). Or if you prefer you can build your own Debian package from the source:

# Retrieve the source
git clone https://github.com/tcobbs/ldview
# Build the package
cd ldview/QT
# Install the package
sudo dpkg -i ldview-4.3-debian-jessie.amd64.deb

Then you have /usr/bin/LDView available.

Putting it together

After that, adapting the script to run on linux was pretty straightforward:


GENERAL_PARAMS="-Antialias=0 -LineSmoothing=0 -TransDefaultColor=0 -DefaultColor3=0xFFFFFF -BackgroundColor3=0xFFFFFF -ProcessLDConfig=1 -MemoryUsage=2"

GEOMETRY_PARAMS="-Seams=1 -SeamWidth=50 -BoundingBoxesOnly-0 -Wireframe=0 -RemoveHiddenLines=0 -WireframeFog=0 -WireframeThickness=5 -BFC=0 -ShowHighlightLines=1 -EdgesOnly=0 -ConditionalHighlights=1 -ShowAllType5=0 -ShowType5ControlPoints=0 -PolygonOffset=1 -BlackHighlights=1 -EdgeThickness=5"

EFFECTS_PARAMS="-Lighting=1 -UseQualityLighting=1 -SubduedLighting=0 -UseSpecular=1 -OneLight=0 -LightVector=-1,1,1 -OptionalStandardLight=1 -DrawLightDats=1 -NoLightGeom=0 -StereoMode=0 -CutawayMode=0 -SortTransparent=1 -UseStipple=0 -UseFlatShading=0 -PerformSmoothing=1"

PRIMITIVES_PARAMS="-AllowPrimitiveSubstitution=1 -TextureStuds=0 -HiResPrimitive=1 -UseQualityStuds=1 -CurveQuality=12 -TextureFilterType=9984"

SAVE_PARAMS="-AutoCrop=1 -ModelSize=500 -SaveActualSize=0 -SaveZoomToFit=0 -SaveWidth=2000 -SaveHeight=2000 -IgnorePBuffer=0 -SaveAlpha=1"


PERSPECTIVE270="-FOV=0.1 -DefaultZoom=0.95 -DefaultMatrix=-0.5,0,-0.866025,-0.496732,0.819152,0.286788,0.709407,0.573576,-0.409576"

for f in $FILES
  ff=$(basename $f)
  echo "Processing $f into $im"
  /usr/bin/LDView $f -SaveSnapshot=output/$im ${PARAMS} ${PERSPECTIVE270}


So you end up with a few (8000+) images in the output subdir, for example:

 3008 3004
 3660 3659
 3738 44772
 60470  15673

The images are very clean, and crisp, making is easy to identify the right drawer with just a glance.

Here is a list of the 100 most common lego pieces with their label.