Realizing still life constraints as a planar tiling

For general discussion about Conway's Game of Life.
User avatar
pcallahan
Posts: 845
Joined: April 26th, 2013, 1:04 pm

Re: Realizing still life constraints as a planar tiling

Post by pcallahan » January 14th, 2020, 2:57 am

Another idea is to forget about the octagons entirely and use these 6 domino-like tiles, assuming the user is able to count.
Screen Shot 2020-01-13 at 10.39.15 PM.png
Screen Shot 2020-01-13 at 10.39.15 PM.png (23.57 KiB) Viewed 9858 times
These must be placed so colors of squares and red boundaries meet. Each corner square contains a number of dots equal to the number of black corner squares in the next two corners going clockwise. So when the tiles are placed, the dots give a quick visual indication of the number of neighbors.

This shows a block, a ship, a beehive, and and eater. It is easy to see that every black square contains two or three dots, and no white square contains exactly three dots. The tile without any dots is not really needed here but it can be placed around the boundaries.
Screen Shot 2020-01-13 at 10.39.47 PM.png
Screen Shot 2020-01-13 at 10.39.47 PM.png (111.28 KiB) Viewed 9858 times
The tiles can be contoured to force the squares to line up by color, but the user is responsible for enforcing the cell counts.

I think if these were made with heavy enough material, like dominoes or mahjongg tiles, they might actually be fun to work with. I can only guess since I had to do it in Google draw. Another point is that they don't enforce any totalistic rule or the still-life property, so they could be used to set up and visualize the next step of any totalistic rule including life.

The disadvantage, of course, is that there is a brain involved in the process, if minimally. You would not be able to get a still life by some process of shaking the tiles together or translate it into a molecular computer. I wonder if these could be the basis of an actual game, e.g. pick some tiles randomly and build a still-life for points.

Update: we can make the counting automatic (e.g.) by clipping the corners off the above tiles and turning them into octagons. Then we can fill in the gaps with tiles that enforce the count. I am not sure if this results in a smaller tiling than the original one in this thread. At some point, the question is just whether the tiles vary too much in size to be usable.

Update 2: The same tile set with interlocking boundaries to force colors.
Screen Shot 2020-01-14 at 10.00.31 AM.png
Screen Shot 2020-01-14 at 10.00.31 AM.png (47.35 KiB) Viewed 9831 times
Note that this tile set can be used for assembling non-stable Life patterns too. I think I've hit my attachment limit on this post, but by assembling three blocks in a row, you can see that two white squares above and below have a count of three (birth) and two black squares on the ends each have only one neighbor and will die.

User avatar
pcallahan
Posts: 845
Joined: April 26th, 2013, 1:04 pm

Re: Realizing still life constraints as a planar tiling

Post by pcallahan » January 15th, 2020, 11:48 pm

Note that we can turn this into an automatic still life tiling by moving slightly into 3D. The idea is sketched below (and I emphasize it's just the idea, not a complete construction).
Screen Shot 2020-01-15 at 7.30.57 PM.png
Screen Shot 2020-01-15 at 7.30.57 PM.png (89.88 KiB) Viewed 9790 times
The dots can be placed so that they have octagonal symmetry. "Color" the dots in a quadrant in clockwise order according to the two following quadrants, also in clockwise order. But instead of using colors, use bumps and dents. Now when the tiles are placed, the four quadrants incident to the same corner will form a symmetric octagon of bumps and dents representing neighbor counts. The semi-transparent blue octagons would have complementary bumps and dents so they can only be placed on a matching neighborhood, but may be rotated.

We could support flips I guess by having bumps and dents on both sides, but if one side is flat any we're limited to rotations, we have:

For live cells, counts 2 and 3, for 4+7 = 11 octagons total.
For dead cells, counts 0, 1, 2, 4, 5, 6 for 1+1+4+10+7+3 = 26 octagons total.

Note that there are only 3 neighborhoods of 6 cells, because one of them causes internal overcrowding and doesn't work for a still life.

So that gives us 37 octagons and 6 squares for 43 distinct pieces, ignoring the previous ways of splitting up octagon neighborhoods. This is not conceptually any better than the pure 2D tiling, but it could be easier to work with because the pieces are all about the same size.

The above is mainly for completeness, because I think that inspecting the dots visually may be adequate for using this as a puzzle and it really reduces the tile count by a lot, besides being more generalizable.

Update: A visual approach with octagonal symmetry, using "flower petals."
Screen Shot 2020-01-16 at 12.06.09 AM.png
Screen Shot 2020-01-16 at 12.06.09 AM.png (112.91 KiB) Viewed 9772 times
Update 2: A mildly amusing aside (at least I find it so). After making these 6 tiles in Google draw, I decided to construct all rotations ahead of time to aid in making patterns out of them. 24 rotations I thought? Wait, no, some are symmetric and have duplicates. I went through the process of eliminating duplicates and was surprised that the result was a nice number like 16. It took me about a day to realize that obviously there are 16 2x2 bitmap patches before you start reducing the set with rotational symmetry. I completely forgot since I had been treating them as geometric objects so long.

Here's a link to the a drawing document with the tiles if anyone wants to copy it and try it out. https://docs.google.com/drawings/d/18aF ... lLdJs/view

Update 3 An alternative to matching dots to two chosen neighbors would be to match all three neighbors in each 2x2 grid by splitting the dots across boundaries. So one dot counts the diagonal, and each half dot counts the horizontal or vertical neighbor. This could be used to replicate the actual neighbors with correct spacing inside each assembled tile, sometimes talking a half dot each from adjoining quadrants. I might try to make some tiles like that, but I'm a little reluctant to split something that is already small. I think the petal design makes the neighbor connections very clear.

Update 4 Here's the split-dot solution if my comments above weren't clear. I did not try to add jigsaw contours, but this shows the idea. Now the dots in each compound cell form an exact image of the live neighbors around it. I think that's an interesting property and could help for non-totalistic rules, but I still prefer the flower petals.
Screen Shot 2020-01-16 at 9.22.50 PM.png
Screen Shot 2020-01-16 at 9.22.50 PM.png (41.55 KiB) Viewed 9734 times

User avatar
pcallahan
Posts: 845
Joined: April 26th, 2013, 1:04 pm

Re: Realizing still life constraints as a planar tiling

Post by pcallahan » January 28th, 2020, 3:24 pm

Revisiting the tiles (e.g. here) I noticed that there is another way to get symmetry besides octagons, which increases symmetry and I think results in more intuitive tiles as well, since the Moore neighborhood is not really an octagon.

If we continue to treat cells as squares and count neighbors by quadrant, the quadrants with one neighbor can be treated identically (unlike with octagons). Specifically, take this cell neighborhood:

Code: Select all

a b c
d e f
g h i
Arbitrarily grouping neighboring cells (there are two choices) we count the neighbors in quadrants clockwise around the center e as b+c, f+i, h+g, d+a. By doing this, a given neighborhood is represented as a cycle of values in {0, 1, 2}. E.g. (0, 1, 2, 0) is a neighborhood in which b+c=0, f+i=1, h+g=2, and d+a=0. The total count is 3 so birth or survival occurs in cell e.

If we represent these neighbors as tiles with boundaries, allowing flips and rotations, we can reduce the number of neighborhoods by a lot. In fact, treating 0+1 and 1+0 the same in each quadrant results in more reduction than maintaining 0-1, 1-0 order around an octagon.

For still lifes, we can also rule out tiles with 7 or 8 neighbors total, since they are internally overcrowded, as well as 6 neighbors grouped as (0, 2, 2, 2) for the same reason.

Here is the complete set of 27 tiles. Black tiles are live. White tiles are dead. Light blue tiles go in-between.
tiles.png
tiles.png (43.13 KiB) Viewed 9676 times
This is kind of a lot but not crazy (note that the game Blokus uses 21 distinct pieces for each player for a total of 84). No doubt we could reduce the number with some splitting rules, but I think that harms the usability of physical tiles.

(Assume for now you can't link black and white tiles directly. I can fix that by tweaking contours. It may not matter anyway. You can chain together 2-neighbor black and white tiles but you can't tile the plane with them.)

Like the previous construction, the in-between tile represent 2x2 windows. These tiles have a zig-zag where they join so they cannot be flipped relative to each other (which would reverse the count of cells around the quadrants and change the meaning). For handling, it's preferable if the tiles are about the same size, though admittedly the in-between ones are bigger than the cells (in the very first from 2016, they were smaller, and this is adjustable).

Here's the eater done with these tiles:
eater.png
eater.png (54.15 KiB) Viewed 9676 times
And here's the block on table:
b_on_t.png
b_on_t.png (67.32 KiB) Viewed 9676 times
I'm still working on the best contours. I just used polygon points that I found by trial and error, and then rotated them around a square. If I get ambitious, I can use bezier curves for more of a jigsaw puzzle effect.

Note: this opens up the possibility of making stackable tiles for computing Life generations. These would require some additional surface features (and get a little tricky if you wanted to make them flippable). I am skeptical that this would be a fun activity for human beings, but still life construction is essentially a jigsaw puzzle, so it has more potential.

A link to 27 transparent PNGs of tiles on Google drive: https://drive.google.com/drive/folders/ ... sp=sharing

Finally, here's a python script that creates the PNGs in imagemagick.

Code: Select all

import math

WIDTH = 50
HEIGHT = 200 / math.sqrt(2) - WIDTH

def rotation(theta):
  cosv = math.cos(math.radians(theta))
  sinv = math.sin(math.radians(theta))

  def rotate(pair):
    x, y = pair
    return (round(cosv * x - sinv * y, 12),
            round(sinv * x + cosv * y, 12))

  return rotate

def scaling(r):
  def scale(pair):
    x, y, = pair
    return x * r, y * r
  
  return scale

W2 = WIDTH-25
H2 = HEIGHT-25

def flip(pair):
  x, y = pair
  return x, -2 * H2 - y

def to_svg(origpath, r = 1.0):
  path = list(map(scaling(r), origpath))
  return " ".join(["M %5.3f, %5.3f" % path[0]] +
                  ["L %5.3f, %5.3f" % pair for pair in path[1:]] +
                  ["Z"])

PATH1 = [(-W2, -H2), (-8, -H2), (-12, -H2 - 20), (12, -H2 - 20), (8, -H2), (W2, -H2)]
PATH2 = [(-W2, -H2), (-15, -H2), (-25, -H2 - 25), 
         (-8, -H2 - 30), (-8, -H2 - 18), (8, -H2 - 18), (8, -H2 - 30),
         (25, -H2 - 25), (15, -H2), (W2, -H2)]
PATH1F = list(map(flip, PATH1))
PATH2F = list(map(flip, PATH2))
EMPTY = [(-W2, -H2), (W2, -H2)]

PATHS = [[EMPTY, PATH1, PATH2],
         [EMPTY, PATH1F, PATH2F]]

COLOR = ["white", "black"]

def tile_path(quadrants):
  result = []
  for i in range(4):
    count = quadrants[(i + 1) % 4] + quadrants[(i + 2) % 4]
    tooth = ([(-WIDTH, -HEIGHT)] + PATHS[quadrants[i]][count] + 
             [(WIDTH, -HEIGHT), (WIDTH + 16, -HEIGHT + 9), (HEIGHT - 16, -WIDTH - 9)])
    result.extend(map(rotation(90 * i - 45), tooth))
  return result

def cell_path(state, quadrants):
  result = []
  for i in range(4):
    path = [(x, -HEIGHT - WIDTH - y) for x, y in PATHS[state][quadrants[i]]]
    tooth = [(-WIDTH, -WIDTH)] + path + [(WIDTH, -WIDTH)]
    result.extend(map(rotation(90 * i - 45), tooth))
  return result

def pattern(x, y, grid, scale, size):
  lines = []
  lines.append("-stroke none")
  for i in range(len(grid)): 
    for j in range(len(grid[i])): 
      color = COLOR[grid[i][j]]
      lines.append("-fill %s -draw 'rectangle %s %s %s %s'" % (color, 
                                                               x + j * size - size, y + i * size - size,
                                                               x + j * size, y + i * size))
  lines.append("-fill lightblue -stroke gray")
  for i in range(len(grid) - 1): 
    for j in range(len(grid[i]) - 1): 
      quadrants = (grid[i][j], grid[i][j + 1], grid[i + 1][j + 1], grid[i + 1][j])
      lines.append("-draw 'translate %d, %d path \"%s\"'" %
                   (x + j * size, y + i * size, to_svg(tile_path(quadrants), scale)))
  return lines

def all_cells():
  result = {}
  
  for a in range(3):
    for b in range(3):
      for c in range(3):
        for d in range(3):
          forward = (a, b, c, d)
          reverse = forward[::-1]
          canonical = min(
            min(forward[-i:] + forward[:-i] for i in range(4)),
            min(reverse[-i:] + reverse[:-i] for i in range(4)))
          if forward == canonical and sum(forward) <= 6:
            result.setdefault(sum(forward), []).append(forward)

  return result

lines = ["magick -size 700x600 canvas:none -fill lightblue -stroke gray"]

x = 70
y = 70
for a in range(2):
  for b in range(2):
    for c in range(2):
      for d in range(2):
        quadrants = (a, b, c, d)
        if quadrants == min([quadrants[-i:] + quadrants[:-i] for i in range(4)]):
          lines.append("-draw 'translate %d, %d path \"%s\"'" % (x, y, to_svg(tile_path(quadrants), 0.5)))
          x += 110

by_count = all_cells()

x = 70
y = 200
state = 1
for count in [2, 3]:
  for quadrants in by_count[count]:
    lines.append("-fill %s -draw 'translate %d, %d path \"%s\"'" % (COLOR[state], x, y, to_svg(cell_path(state, quadrants), 0.5)))
    x += 110

x = 70
y += 110
state = 0
for count in [0, 1, 2]:
  for quadrants in by_count[count]:
    lines.append("-fill %s -draw 'translate %d, %d path \"%s\"'" % (COLOR[state], x, y, to_svg(cell_path(state, quadrants), 0.5)))
    x += 110

x = 70
y += 110
state = 0
for count in [4]:
  for quadrants in by_count[count]:
    lines.append("-fill %s -draw 'translate %d, %d path \"%s\"'" % (COLOR[state], x, y, to_svg(cell_path(state, quadrants), 0.5)))
    x += 110

x = 70
y += 110
state = 0
for count in [5, 6]:
  for quadrants in by_count[count]:
    if quadrants != (0, 2, 2, 2):
      lines.append("-fill %s -draw 'translate %d, %d path \"%s\"'" % (COLOR[state], x, y, to_svg(cell_path(state, quadrants), 0.5)))
      x += 110
lines.append("tiles.png")
print(" \\\n").join(lines)

lines = ["magick -size 600x600 canvas:none -fill lightblue -stroke gray"]
eater = [
  [0, 0, 0, 0, 0, 0],
  [0, 0, 0, 1, 1, 0],
  [0, 0, 0, 0, 1, 0],
  [0, 1, 1, 1, 0, 0],
  [0, 1, 0, 0, 0, 0],
  [0, 0, 0, 0, 0, 0]]

lines.extend(pattern(100, 100, eater, 0.5, 100))
lines.append("eater.png")
print(" \\\n").join(lines)

lines = ["magick -size 600x700 canvas:none -fill lightblue -stroke gray"]
block_on_table = [
  [0, 0, 0, 0, 0, 0],
  [0, 0, 0, 1, 1, 0],
  [0, 0, 0, 1, 1, 0],
  [0, 0, 0, 0, 0, 0],
  [0, 1, 1, 1, 1, 0],
  [0, 1, 0, 0, 1, 0],
  [0, 0, 0, 0, 0, 0]]

lines.extend(pattern(100, 100, block_on_table, 0.5, 100))
lines.append("b_on_t.png")
print(" \\\n").join(lines)

Last edited by pcallahan on February 12th, 2020, 2:42 pm, edited 2 times in total.

hkoenig
Posts: 258
Joined: June 20th, 2009, 11:40 am

Re: Realizing still life constraints as a planar tiling

Post by hkoenig » January 28th, 2020, 6:04 pm

(skipping over the recent posting)

I like the split dots better. With the petals, it isn't entirely obvious which quadrants are contributing. The split dots show that orthogonally, it takes two tiles to contribute, but only one diagonally.

User avatar
pcallahan
Posts: 845
Joined: April 26th, 2013, 1:04 pm

Re: Realizing still life constraints as a planar tiling

Post by pcallahan » January 28th, 2020, 6:29 pm

hkoenig wrote:
January 28th, 2020, 6:04 pm
(skipping over the recent posting)

I like the split dots better. With the petals, it isn't entirely obvious which quadrants are contributing. The split dots show that orthogonally, it takes two tiles to contribute, but only one diagonally.
I agree that it's a more faithful rendering of the neighborhood, and in that sense is a better visualization. I still like the petals but that's purely a matter of personal preference.

User avatar
pcallahan
Posts: 845
Joined: April 26th, 2013, 1:04 pm

Re: Realizing still life constraints as a planar tiling

Post by pcallahan » January 30th, 2020, 12:05 pm

hkoenig wrote:
January 28th, 2020, 6:04 pm
(skipping over the recent posting)

I like the split dots better. With the petals, it isn't entirely obvious which quadrants are contributing. The split dots show that orthogonally, it takes two tiles to contribute, but only one diagonally.
Here's another variation, and maybe it's the right one for purists. All it does is duplicate the 2x2 neighborhood in each quadrant, but with an appropriate rectangle on boundaries so everything adds up to squares when placed. Each cell bounded by grid lines is a complete representation of the neighborhood. Shown here with block and eater.
Screen Shot 2020-01-30 at 7.51.58 AM.png
Screen Shot 2020-01-30 at 7.51.58 AM.png (39.93 KiB) Viewed 9630 times
This is starting to look way too much like the way I've actually implemented neighborhoods in some programs. I wonder if anyone else has presented the tiles in this form before. I'm surprised I got side-tracked with octagons before doing this.

As a visualization, it might satisfy those reasonably familiar with Life. I think it is a lot for a novice to absorb at once. Also, I think I'd get a headache if I tiled my floor this way.

There should be enough room for jigsaw contours as long as they only go 1/8 of the way into each tile.

Update: I like this variation better, shrinking the quadrants into corners and leaving space to show the original pattern cells.
Screen Shot 2020-01-30 at 10.20.03 AM.png
Screen Shot 2020-01-30 at 10.20.03 AM.png (37.5 KiB) Viewed 9620 times
Update 2: The more I look at the above, the more I like it. It seems to function as training wheels to learn how to just run these patterns on paper or in your head (which I believe some of the "gods of old" are able to do). It does not make it quite as easy as counting dots or petals. E.g., it threw me for an instant when that white "glider" showed up in the eater before I realized it represents the 5 dead cells in the neighborhood. There is a little more memorization to do in order to verify still lifes visually, but in the process, you actually get a better sense of how to see the neighborhoods without any annotations.

The second set also leaves a lot of space for jigsaw contours. I am still thinking in terms of a game. Possibly the all-blank tile should just be omitted. Is there a way you could score or compare patterns like poker hands?

Update 3: (and seconds later) Scrabble! The tiles can have the overall feel of Scrabble pieces, except larger and perfectly square. The jigsaw edges might be unnecessary. Unlike Scrabble, the determination of valid patterns would not be dictionary dependent. We don't necessarily need to limit it to still lifes as long as there is some way to score neighborhoods.

mniemiec
Posts: 1590
Joined: June 1st, 2013, 12:00 am

Re: Realizing still life constraints as a planar tiling

Post by mniemiec » January 30th, 2020, 6:48 pm

pcallahan wrote:
January 30th, 2020, 12:05 pm
Update: I like this variation better, shrinking the quadrants into corners and leaving space to show the original pattern cells.Screen Shot 2020-01-30 at 10.20.03 AM.png

Update 2: The more I look at the above, the more I like it. It seems to function as training wheels to learn how to just run these patterns on paper or in your head (which I believe some of the "gods of old" are able to do). It does not make it quite as easy as counting dots or petals. E.g., it threw me for an instant when that white "glider" showed up in the eater before I realized it represents the 5 dead cells in the neighborhood. There is a little more memorization to do in order to verify still lifes visually, but in the process, you actually get a better sense of how to see the neighborhoods without any annotations.

The second set also leaves a lot of space for jigsaw contours. I am still thinking in terms of a game. Possibly the all-blank tile should just be omitted. Is there a way you could score or compare patterns like poker hands?
I like these tiles; it only took me a few seconds to see how they fit together (with the 3x3 neighborhoods being shown in miniature in the center of each square). Jigsaw contours on the cell boundaries could be used to enforce creating only valid combinations of adjacent tiles (e.g. putting 2 next to 3 would be syntactically correct, rather than merely semantically incorrect), but aren't strictly necessary if you trust the user to enforce this rule by eye. On the other hand, I though the whole point of this exercise was to produce a set of files that can produce all valid Life still-lifes, and no patterns that aren't still?

I can see how this will produce all valid patterns and only valid patterns, but as it appears to be rules-agnostic, it won't exclude non-still-lifes. It is pretty, though. On the other hand, if you only want to show valid patterns, you could just use the first two tiles, and the we're back to how Life has been represented on square grids from the beginning.

User avatar
pcallahan
Posts: 845
Joined: April 26th, 2013, 1:04 pm

Re: Realizing still life constraints as a planar tiling

Post by pcallahan » January 30th, 2020, 7:26 pm

mniemiec wrote:
January 30th, 2020, 6:48 pm
I can see how this will produce all valid patterns and only valid patterns, but as it appears to be rules-agnostic, it won't exclude non-still-lifes. It is pretty, though. On the other hand, if you only want to show valid patterns, you could just use the first two tiles, and the we're back to how Life has been represented on square grids from the beginning.
You're right that this is a detour from actually enforcing still life rules. I was thinking about hkoenig's preference for the split dots and trying to take that to its logical conclusion. But these could be turned into 3D still life tiles by having bumps and dents in the mini-neighborhoods and providing a limited set of caps that fit over only the ones consistent with still life patterns. (But you can't do it until you pull them into neighborhoods, or the caps would overlap, unless I'm missing something) There isn't enough symmetry to create a small set of caps, but it would be a valid construction.

What I actually see in this case is a way to enhance human pattern-matching. I do see more when the neighborhoods are collected than when the patterns are presented the normal way with two colored tiles. If I have to, I can force myself to see neighborhoods, but there's some effort involved. The set of neighborhoods consistent with still lifes is also small enough to memorize pretty easily as a short-cut to counting (i.e. there would be a lot of injected-molded caps to make, but I think they fit into the brain very well: there are a lot fewer than Chinese characters for instance).

But aside from practical importance or direct relevance to the original thread, I thought this made a very striking visualization of neighborhoods.

Update: Instead of having a custom cap for every neighborhood, I wonder how far you could make it with some very simple lego-like pieces to snap on top in layers and reduce the number of possibilities. I know simsim314 worked on something like this, so my idea might not be new. What if you had four pieces that could be snapped over any two adjacent bumps/dents. If they're both the same, it keeps them unchanged. Otherwise, you can take adjacent (0,1) depending on the piece, either keep them order (0, 1) or swap to (1, 0). Over enough applications, the neighborhood can be put in canonical form and tested with just a few tiles. It's a bit tedious, but the tile count might be very small. So far, it's 10.

Update 2: I wonder if we can get by with just (0, 0) -> (0, 0), (1, 1) -> (1, 1), and (0, 1) -> (1, 0). That is, find a "domino" covering of bits for which bits always swap if two adjacent domino are different. If we're limited to just the 8 neighbors around the center, we're limited by the fact that an alternating 0-1 pattern with count 4 would alternate each layer. But maybe we could add some bits in the neighborhood that are initially zero. This is getting far from practicality, but it's a puzzle.
Last edited by pcallahan on January 30th, 2020, 9:43 pm, edited 2 times in total.

hkoenig
Posts: 258
Joined: June 20th, 2009, 11:40 am

Re: Realizing still life constraints as a planar tiling

Post by hkoenig » January 30th, 2020, 9:01 pm

pcallahan wrote:learn how to just run these patterns on paper or in your head (which I believe some of the "gods of old" are able to do)
Back before computers, I did use up lots of graph paper (and erasers were cheaper than new paper). Still have some of that around here somewhere. At some point it did become unnecessary to count neighbors, just recognize the patterns.

And the smaller bits looks better to me. A thin frame of a third color around them would help offset the neighbor pattern from the center of the bit.

User avatar
pcallahan
Posts: 845
Joined: April 26th, 2013, 1:04 pm

Re: Realizing still life constraints as a planar tiling

Post by pcallahan » January 31st, 2020, 7:18 pm

hkoenig wrote:
January 30th, 2020, 9:01 pm
Back before computers, I did use up lots of graph paper (and erasers were cheaper than new paper). Still have some of that around here somewhere. At some point it did become unnecessary to count neighbors, just recognize the patterns.
I had an early TRS-80 computer before I ever heard of Life, so I never had to use graph paper. I am not sure I would have had the patience for it. I probably have more patience now and sometimes like working things out on paper but often go with "virtual paper" like Google draw. But having manipulatives like tiles is also fun (maybe I need to open up a new kind of Montessori school and find parents willing to test these things out on their kids).

I also wanted to get back to this.
mniemiec wrote:
January 30th, 2020, 6:48 pm
I can see how this will produce all valid patterns and only valid patterns, but as it appears to be rules-agnostic, it won't exclude non-still-lifes.
As I said, the concentrated neighborhoods could be made into bumps and dents. True, we are no longer talking about a planar tiling. You get a lot of different patterns of bumps and dents that have the same count, and that's a problem. I noticed a general way to put them in canonical form with just two new pieces. Let's say the dent is one unit deep and the bump is one unit high. They are squares and adjacent around the neighborhood (the middle has a different shape to match a cap piece). Use these two pieces:
  • A square of thickness w+2 that fits into a dent (w is arbitrary but chosen to avoid coincidences in stacking).
  • A domino of two joined squares, one of thickness w and the other of thickness w+4, aligned at their central planes.
The picture below shows the idea in cross-section. Given a series of adjacent dents and bumps (linear here but they could be around a ring) You use the square to move a value up unchanged, and use the domino to swap two adjacent values and move a bump. In this case, the original blue pattern is canonicalized to two bumps at the right through successive operations (and maybe this could be used to reduce a planar tiling too, but I'm not sure how to go outside to inside).
Screen Shot 2020-01-31 at 2.32.09 PM.png
Screen Shot 2020-01-31 at 2.32.09 PM.png (77.65 KiB) Viewed 9564 times
(Open: does this admit unwanted tilings? If so, I believe it's fixable.)

In practice, this would result in a tedious process of dropping in tiny bits of plastic with tweezers. :wink: But I am now convinced that you can get a canonical totalistic Moore neighborhood with just 8 tiles in 3D and that's a surprise. You would want to move the bumps to a place starting at a corner, for instance, but it would not have to be the same corner with rotations, so there might not be all that much movement needed. Then you just add caps to recognize 2 or 3 around live, or 0, 1, 2, 4, 5, 6 around dead (so 16, but we can probably reduce it further).
hkoenig wrote: And the smaller bits looks better to me. A thin frame of a third color around them would help offset the neighbor pattern from the center of the bit.
blocktiles.png
blocktiles.png (12.13 KiB) Viewed 9564 times
I did this in imagemagick so I can generate larger patterns than I can make in Google draw. I am not sure about lines. They may clarify things, but I was going for a minimal aesthetic, and it seems like the black/white contrast is already enough to remove ambiguity.

I feel as if still life violations would jump out at me, but I should probably test that with real non-still-life patterns. Update: here's a section of the infinite houndstooth p2 oscillator (which conveniently uses all tiles at all orientations. Do the births and deaths jump right out?
ht.png
ht.png (11.72 KiB) Viewed 9557 times
Here's a python script to generate the imagemagick command for eater and block on table:

Code: Select all

import math

COLORS = ["white", "black"]

def tile(quadrants, x, y, side, scale):
  lines = []
  length = side * scale
  inner = side * (scale - 3) + 1
  for i in range(4):
    rotate = 90 * i - 180
    lines.append("-stroke none")
    (a, b, c, d) = quadrants[i:] + quadrants[:i]
    lines.append("-fill %s -draw 'translate %d %d rotate %d translate 1 1 rectangle 0 0 %d %d'" %
                 (COLORS[a], x, y, rotate, length - 1, length - 1))
    lines.append("-fill %s -draw 'translate %d %d rotate %d translate %d %d rectangle 0 %d %d %d'" %
                 (COLORS[b], x, y, rotate, inner, inner, side * 2, side * 2 - 1, side * 3 - 1))
    lines.append("-fill %s -draw 'translate %d %d rotate %d translate %d %d rectangle 0 0 %d %d'" %
                 (COLORS[c], x, y, rotate, inner, inner, side * 2 - 1, side * 2 - 1))
    lines.append("-fill %s -draw 'translate %d %d rotate %d translate %d %d rectangle %d 0 %d %d'" %
                 (COLORS[d], x, y, rotate, inner, inner, side * 2, side * 3 - 1, side * 2 - 1))
    lines.append("-fill none -stroke red -draw 'translate %d %d rotate %d translate 0 0 "
                 "path \"M %d %d L %d %d L %d  %d\"'" %
                 (x, y, rotate, length, inner, inner, inner, inner, length))
  lines.append("-stroke lightgray -draw 'translate %d %d path \"M 0 %d L 0 %d\" path \"M %d 0 %d 0\"'" %
               (x, y, -length + 1, length -1, -length + 1, length - 1))
  return lines


def pattern(x, y, grid, side, scale):
  size = side * scale * 2 + 1
  lines = []
  for i in range(len(grid) - 1): 
    for j in range(len(grid[i]) - 1): 
      quadrants = (grid[i][j], grid[i][j + 1], grid[i + 1][j + 1], grid[i + 1][j])
      lines.extend(tile(quadrants, x + j * size, y + i * size, side, scale))  
  return lines


lines = ["magick -size 900x700 canvas:skyblue"]
x = 100
y = 100
for a in range(2):
  for b in range(2):
    for c in range(2):
      for d in range(2):
        quadrants = (a, b, c, d)
        if quadrants == min(quadrants[i:] + quadrants[:i] for i in range(4)):
          lines.extend(tile(quadrants, x, y, 7, 5))
          x += 120

eater = [
  [0, 0, 0, 0, 0, 0],
  [0, 0, 0, 1, 1, 0],
  [0, 0, 0, 0, 1, 0],
  [0, 1, 1, 1, 0, 0],
  [0, 1, 0, 0, 0, 0],
  [0, 0, 0, 0, 0, 0]]
lines.extend(pattern(100, 250, eater, 7, 5))

block_on_table = [
  [0, 0, 0, 0, 0, 0],
  [0, 0, 0, 1, 1, 0],
  [0, 0, 0, 1, 1, 0],
  [0, 0, 0, 0, 0, 0],
  [0, 1, 1, 1, 1, 0],
  [0, 1, 0, 0, 1, 0],
  [0, 0, 0, 0, 0, 0]]
lines.extend(pattern(500, 250, block_on_table, 7, 5))

lines.append("blocktiles.png")
print(" \\\n").join(lines)

User avatar
pcallahan
Posts: 845
Joined: April 26th, 2013, 1:04 pm

Re: Realizing still life constraints as a planar tiling

Post by pcallahan » February 1st, 2020, 3:00 am

pcallahan wrote:
January 31st, 2020, 7:18 pm
I feel as if still life violations would jump out at me, but I should probably test that with real non-still-life patterns.
For some additional comparisons, here's a glider and blinker. I think the violations mostly jump out, but I might have missed the cell birth on the glider if I wasn't looking for it. This is like learning any other kind of pattern recognition. There aren't that many possible neighborhoods to begin with, taking symmetry into account, and if you're unsure, you can just count the cells.
glbl.png
glbl.png (6.21 KiB) Viewed 9541 times
Here's a more complicated still life.
99a.png
99a.png (13.34 KiB) Viewed 9541 times
It may be worth trying this on completely random patterns to see if I miss any births or deaths. If I just want a totalistic rule, the dominos or petals might be better.

Another gamification idea would be to have manual still life in an interactive program, where you need to click on only the cells that change in order to move to the next generation.

Update:
Here are the neighborhoods up to symmetry grouped by CGOL transition. To identify a still life, it is probably easiest to memorize the all the survival windows for black cells (required) and all the birth windows for white cells (forbidden). (I replaced the first image I posted with one that shows context and is ordered by neighbor count.)
windows.png
windows.png (12.7 KiB) Viewed 9514 times

User avatar
pcallahan
Posts: 845
Joined: April 26th, 2013, 1:04 pm

Re: Realizing still life constraints as a planar tiling

Post by pcallahan » August 8th, 2021, 12:41 am

I decided to revisit the octagon-based still life tiling with a different focus. Instead of minimizing the number of tiles, I would like to have something that's manufacturable and usable. I've been getting more proficient with inkscape and considering doing a laser cut order from Ponoko on 3mm acrylic. I am not totally sure this will produce interchangeable boundaries, but the precision should be high enough (0.2mm kerf for cuts).

Note: a big goal is to have something fun like a jigsaw puzzle even for people who know nothing about CGoL. No matter what they do, if they complete the tiling, they will have to get a still life.

Here are the pieces. I have added a picture of a 1x1 lego tile to illustrate scale. Two of the pieces are smaller, but most are not, so I think it's not something you need tweezers and a jeweler's loupe to assemble.
Screen Shot 2021-08-07 at 8.56.29 PM.png
Screen Shot 2021-08-07 at 8.56.29 PM.png (346.98 KiB) Viewed 5580 times
The grid spacing is 25mm or just under 1 inch.

Some explanation: This switches the tiling around from the original by making the inter-cell pieces larger than the cell pieces. The advantage of doing so is that you can build with them first, and if you already know the still life rule (2-3 neighbors for live cells, and anything but 3 for empty cells) then you can guarantee that the gaps are fillable.

For stability, the inter-cell pieces interlock like jigsaw pieces. The inter-cell pieces are normally flip-symmetric and therefore never need to be flipped, but the jigsaw connectors introduce handedness by following paths on the boundary between live and dead cells. Traversing this boundary following the direction of connectors, the live cell will always be to the right.

Another thing I added are 3 pieces that establish the boundary. These are also interlocking and frame the exterior empty cells. Given that you can't really extend the plane infinitely with acrylic, some boundary is unavoidable, and I think these 3 pieces are a small price to pay.

I didn't use all the tile set minimizations. In particular, all 5 empty cells with 1 or 2 neighbors are given explicitly as tiles. I could have reduced this to 4 tiles, but it's not worth the tweezer factor of dealing with a tiny internal piece.

The crowded empty cells (4, 5, or 6 neighbors) are represented with three tiles as discussed much earlier in the thread. In this case, I think usability runs the other way. I could pack many copies of all 17 possibilities on a small sheet of plastic, but the effort of finding the right one may actually exceed that of building it. Though these pieces are small, their placement can be deferred until after the larger ones are assembled.

Here is an assembled still Cis-block on long hook.
Screen Shot 2021-08-07 at 8.55.53 PM.png
Screen Shot 2021-08-07 at 8.55.53 PM.png (593.17 KiB) Viewed 5580 times
I put it together manually in inkscape, which helpfully snaps shapes together (but doesn't always guess what I want to snap). My order of construction was: inter-cell tiles, live cells, "lonely" cells with 1 or 2 neighbors, "crowded" cells with 4, 5, or 6 neighbors, and finally the border. I think it may make sense to add the border before placing any cells, but it requires a little guesswork to get started if the gaps are not filled.

User avatar
pcallahan
Posts: 845
Joined: April 26th, 2013, 1:04 pm

Re: Realizing still life constraints as a planar tiling

Post by pcallahan » August 8th, 2021, 1:14 pm

I was in a hurry last night, but I think that for live cells, it's good to have interlock so they can be assembled before placing them. This results in a smaller gap filler than the 1cm circle I used above, but it's not too small compared to a 1x1 lego tile, which I'm going to keep as my gold standard of usability. Here are what the live cells look like using an "ax-head" of alternating convex and concave 90° arcs.
Screen Shot 2021-08-08 at 10.03.23 AM.png
Screen Shot 2021-08-08 at 10.03.23 AM.png (441 KiB) Viewed 5559 times
They're interlocking, big enough to work with, and aesthetically pleasing in my opinion. But will they really fit using 3mm laser cut acrylic? That's an experiment that costs money. Before I take the leap, I need to collect some frequencies on symmetric neighborhoods in small still lifes to come up with a good tile set, e.g. that could be used to build all still lifes up to 20 cells (less if that's unreasonable).

A note on whether to split tiles or not: I sometimes think that going from 9 assembled tiles to 5 disassembled ones is not a "big win." The is probably because I'm asking the wrong question. We aren't trying to assemble exactly one combined tile but a multiset sufficient to complete the pattern. With that in mind, the appropriate analysis is to take all patterns you want to construct and build the minimal tile multiset needed. I suspect that the split tiles will do much better in this regard since they can be mixed to create different proportions. So for instance if I provided all 17 instances of crowding neighborhoods, a lot more tiles might be needed just to handle a few patterns that made disproportionate use of uncommon crowding cases.

Update: This was not why I chose the ax heads, but maybe someone has noticed (if so, quicker than me!) that these pieces tile with themselves very nicely. It's a common decorative pattern in fact. So you could put 64 of these in an 8x8 checkerboard on less than a 6cm by 6cm section of plastic as spare parts. You do not need any extras, since the ones inside the 2-teeth wheels should be enough, but they are easy to lose.

User avatar
pcallahan
Posts: 845
Joined: April 26th, 2013, 1:04 pm

Re: Realizing still life constraints as a planar tiling

Post by pcallahan » September 2nd, 2021, 4:59 pm

Well, this is exciting. I got my Ponoko order (also one for Margolus tiles, which will be another thread if I get to it). The material is 3mm-thick white acrylic, and laser cut is sufficient for this purpose. The smallest pieces are under 8mm in diameter, but most are bigger. They're not fragile either. Here's what it looks like right now, after removing the top protective layer and all the sticky paper on both sides of three pieces that make up a 2-neighbor live cell.
20210902_134220.jpg
20210902_134220.jpg (203.39 KiB) Viewed 5394 times
I did not know I would need to peel all these little pieces, and that's going to be a lot of work.

But... I just realized it gives me a quick and dirty solution to having two colors of tile. I had planned to do another order on blue acrylic and still might, but for now I will only peel the live cell tiles. Then I get white cells on a tan background. Not the prettiest, but it'll do.

One downside to laser-cutting is it removes a lot of material (claimed 0.2mm kerf, though it seems like more). So the pieces are kind of jiggly. Bigger pieces or thicker acrylic could help, but both of these add to the cost. These are at about the limits where a human being would want to work with them. I think if I made them a little bigger, this could be an interesting toy even for non-Life people.

Challenge: I did this in Inkscape with copy-paste and made at least one mistake (I hope just one). See if you can find where I missed a cut between two pieces. I will fix that with a knife some time and avoid the mistake on the next order.

Update: As a proof of concept and test that the pieces are interchangeable, I put together a snake, which was not one of the patterns in my layout. The principle works and the pieces are not that hard to manipulate, even the "axe heads" and crowded quadrants. The main problem is as noted above. Cutting removes too much material. I could make the pieces bigger. I could even consider an alternative material. I wonder if birch plywood (which is cheaper) would actually do better than acrylic. It would also be possible to paint some pieces. This would be a lot more folk-art looking than the acrylic approach. Well, I won't be paying for injection molds unless a lot more people are interested than I would expect.
20210902_153533.jpg
20210902_153533.jpg (123.99 KiB) Viewed 5380 times
BTW, I am happy to make the SVG file available to anyone who wants to make their own set. I have a corrected copy that is not missing a cut.

Update 2 I think the 0.2mm kerf is accurate. E.g., in the above pattern, I found that pushing the puzzle together and measuring comes to about 149mm in width, instead of 150mm, which is exactly what's expected from the 5 gaps.

But the "jiggle factor" is way more than 0.2mm. Why? I bet it's my fault. I went very conservative on the jigsaw connections between interlocking pieces. These shapes just slide a lot horizontally when there is 0.2mm removed parallel to the cut. I was trying to make it simple, like a dovetail, and also asymmetric so the piece could not be flipped relative to another.
20210902_153533 (1).jpeg
20210902_153533 (1).jpeg (17.63 KiB) Viewed 5347 times
My big concern was fragility. I tried to keep curves at least 4mm apart if possible. But I can probably go down to 2mm safely. Something with a right angle that really locks the piece in place would be an improvement. I have limited space to work though.

User avatar
pcallahan
Posts: 845
Joined: April 26th, 2013, 1:04 pm

Re: Realizing still life constraints as a planar tiling

Post by pcallahan » September 6th, 2021, 10:11 pm

I can think of two ways of dealing with jiggly pieces. Minimizing boundary jiggle is the most important, since it will constrain internal pieces. (I also tested this idea by compressing and taping the boundary.)

First, the jigsaw connection can be shaped to minimize the amount of stretching. This connection looks a little weird, but I'm working within a constrained area, and my goal is to have boundaries on both sides perpendicular to the direction of pulling. Then without rotation, you can compress the pieces to be touching (0mm apart) or stretch them to 0.4mm apart. (At intended placement they are 0.2mm apart, because that is the material removed by the laser.) You can rotate a little, pulling one piece about 2.5° away from the interior. I think internal constraints may fix that.
path2005-7.png
path2005-7.png (12.31 KiB) Viewed 5298 times
(I made the laser cut shapes using Inkscape "stroke to object" and "difference" operations.

The second way is to try to make pieces that fit snugly and don't jiggle. If they fit perfectly, the original shapes will suffice. In this case, assume the piece will be laser cut and compensate ahead of time (using Inkscape "union" with the stroke object). For this example, I assume the kerf is 1mm so the compensation is visible.
path4512.png
path4512.png (9.5 KiB) Viewed 5298 times
.

I think this approach gives a higher quality result (i.e. a more usable puzzle). My main concern is if I am correct about the kerf. If it's actually less, the pieces might not fit together at all. The other issue is that the pieces cannot be cut packed together if I do this. But there are relatively few boundary pieces, so it's probably worth the cost of a little wasted acrylic.

Another thought: If I could coat the pieces (at least the boundary) with 0.1mm (100 microns) of lacquer or similar I could get a snug fit. It would have to be uniform and I really don't know what's feasible. Maybe this all points to painted wood as the best solution. I still like the look of the shiny acrylic pieces.

User avatar
benetnasch85
Posts: 31
Joined: March 17th, 2017, 12:09 am

Re: Realizing still life constraints as a planar tiling

Post by benetnasch85 » September 7th, 2021, 12:58 am

All very interesting! I'm looking for a way to make a set with available tools and materials.

Another way to tighten up the boundary would be to indent the boundary pieces on both sides and link them with asymmetric "axe heads" that can be cut separately in a slightly larger size. If the internal locked pieces surrounding the live cells used a slightly smaller version of the same "axe heads", the pieces cut out between adjacent boundary pieces could be used to lock the internal pieces together more tightly as well. This method would work better if the pieces are made larger because sharp corners on the "axe heads" with radius smaller than the kerf would not fill out the tiling or help lock the larger pieces together.

A more ambitious project would be to extend this set to 3 dimensions, by making all of the circles (or parts of circles, if partitioning is still practical) non-flippable, with circular grooves of smaller radius on the bottom if they are "off" and larger radius if they are "on", and with corresponding circular ridges on top to indicate whether the cell will be on or off in the next generation. If I'm counting right, the "on" and "off" circles each come in 36 patterns including plain circles for cells without neighbors. Such a set could be modified to simulate any Life-like rule just by changing which circular pieces have the "on" or "off" ridges on top.

User avatar
pcallahan
Posts: 845
Joined: April 26th, 2013, 1:04 pm

Re: Realizing still life constraints as a planar tiling

Post by pcallahan » September 7th, 2021, 1:52 am

benetnasch85 wrote:
September 7th, 2021, 12:58 am
Another way to tighten up the boundary would be to indent the boundary pieces on both sides and link them with asymmetric "axe heads" that can be cut separately in a slightly larger size.
That is a good idea, and it did not occur to me. I think they could be symmetric as long as they didn't fit anywhere else. The boundary pieces themselves are flip symmetric (except the connectors) and could have flat sides if I was not going for interlock. If the connectors (ax heads or some other locking pattern) could pack with each other, they could use a very small section of the acrylic. There would also be "false ax heads" that are left over in between the border pieces. They sort of work but would have a lot of jiggle.

About the only disadvantage compared to the current setup is the need to join small pieces. It may be a little while before I make another order. It's expensive unless I combine projects, and since none of these are actually useful, it feels a bit frivolous.

Two more pictures, this time of an eater I assembled. The first shows the ugly side of the protective wrapping. It is where the laser burns a lot and there is also manufacturer information (Marga Cipta, an Indonesia company that produces acrylic).
20210906_230308.jpg
20210906_230308.jpg (231.45 KiB) Viewed 5279 times
For the crowded cells, I need to flip pieces sometimes and I see that in my pattern, most of the one-cell quadrant and two-cell half-circle pieces have the same orientation, so unless I'm very selective I show burnt marks or even red printing. I can peel it but then all the pieces would be white.

I peeled the burnt side off some boundary pieces. The boundary can't be confused with live cells. A boundary piece can be flipped as long as all connected boundary pieces are also flipped.
20210906_230449.jpg
20210906_230449.jpg (232.85 KiB) Viewed 5279 times
To flip an assembled pattern, I sandwich it between two pieces of cardboard and hold tight while flipping. It's harder than working with a jigsaw puzzle, but not that bad once you get used to it.

Update: The connector piece would have to be very small, even compared to the ax head in the live cells. Even dropping the distance to 2.5mm between boundaries, there is not much room to work with here, mainly due to the inner corner. One fix is to give the inner corner its own protrusions, but these would also need to compensate for kerf. I think it is preferable to have fewer pieces to put together. (But this did give me a chance to improve my Inkscape skills.)

OK, another idea is to remove the middle section of the inner corner piece (that looks like an arrow) entirely. This updated picture shows the alternatives. The piece isn't that big even when you open up the whole middle space for it. The live cell ax head is shown for comparison. I am not sure how stable it would be.
Screen Shot 2021-09-07 at 12.07.07 PM.png
Screen Shot 2021-09-07 at 12.07.07 PM.png (489.49 KiB) Viewed 5249 times

User avatar
pcallahan
Posts: 845
Joined: April 26th, 2013, 1:04 pm

Re: Realizing still life constraints as a planar tiling

Post by pcallahan » October 5th, 2021, 7:41 pm

I got my latest laser cut order. This post is not about Life at all, but about compensating for kerf in laser cuts. It looks like it should work in principle, but I just barely made it with my test. As part of a larger order that includes the Life tiles, I did a (fairly inexpensive under $4) test of interlocking pieces on "green glass" acrylic that include extra thickness to be removed by the laser. In Inkscape, I add a stroke of a certain thickness, convert to a path, and then take its union with the original object so that when the laser removes this, it will go back to original size.

Based on Ponoko's stated 0.2mm kerf, I used stroke width of 0.16mm, 0.18mm, 0.2mm, 0.22mm, 0.24mm assuming it would fall right in the middle of this range. In fact, the only pieces that fit at all were the ones that compensated for 0.16mm kerf. These fit tightly and require force to align. They are even harder to separate, and run the risk of cracking the acrylic.

So, OK, good for Ponoko. Their laser is actually more precise than advertised. But I am disappointed that I only captured it at an extreme. I was thinking I would get a really good sense of how the pieces fit with different compensations. I also don't think I can rely on kerf staying constant between orders, so it's a little risky.

The order as shipped (with some pieces removed):
20211005_152515 copy.png
20211005_152515 copy.png (855.72 KiB) Viewed 5053 times
The pieces with 0.16mm kerf compensation that fit tightly.
20211005_152515 copy 2.png
20211005_152515 copy 2.png (201.31 KiB) Viewed 5053 times
If I do this again, I'll stick to the simple connector because it works well as long as there is no lost material.
Finally at the other extreme, two pieces that don't fit at all.
20211005_152515.jpg
20211005_152515.jpg (13.84 KiB) Viewed 5053 times
I'll have another post with the new set of Life tiles (and a Python script for creating some of the SVG) when I have time to look it over. This uses border pieces with the new connector that has less slide (I checked). So it should be an improvement. If I can compensate consistently for kerf, I can make a very nice set of border pieces that fit snugly. (Just not so much that you crack them trying to get them apart.)
Last edited by pcallahan on October 7th, 2021, 2:50 pm, edited 1 time in total.

User avatar
pcallahan
Posts: 845
Joined: April 26th, 2013, 1:04 pm

Re: Realizing still life constraints as a planar tiling

Post by pcallahan » October 6th, 2021, 4:12 pm

The new connector shapes improved some things, but they are still not quite satisfactory. There's less jiggle and I might go as far as saying it has changed from an assembly hindrance to more of an annoyance. I don't feel like they'll scatter if I put my hand down too hard, but I still have to be careful dragging the pattern. The main problem to fix is the stretch. The original connectors had a shallow angle that magnified the effect of lost material, while these are designed to keep the gap perpendicular to the direction of stretch. Here's an example with border pieces:
20211006_094927.jpg
20211006_094927.jpg (109.25 KiB) Viewed 5029 times
The red oval shows how the old pieces stretch more than 2mm beyond the new ones. The new ones are so close to the expected 12.5cm length I had to persuade myself the pieces were as long as I expected (25mm each). At 0.2mm kerf, the four gaps could stretch out 0.8mm, which is probably what I'm seeing. The ruler isn't precise enough for sub-mm measurement, and the kerf may really be less than 0.2mm (see last post).

The kerf-compensated pieces are shown to the right (clear acrylic) and they have a much tighter fit. I don't know when I'll place another order, but I really would like to have a border that doesn't jiggle at all, even if it means wasting some material and paying for two boundary cuts.

The new connectors on the 2x2 neighborhood tiles are also an improvement in terms of stretch:
20211006_124307.jpg
20211006_124307.jpg (95.13 KiB) Viewed 5029 times
The only disappointment is that the asymmetry doesn't prevent joining a tile with another that's been flipped. (See tiles to the right.) The internal cells make this irrelevant. No matter what, you need to leave appropriate cell shapes in between. But it's still a usability issue. I found myself placing some incorrectly. I think I just need to make it thicker at the top with more of a difference between left and right side. These aren't as amenable to kerf compensation because I really want to cut all the pieces together like a jigsaw puzzle.

Finally, the main point of the second order was to get two colors of acrylic. I made the live cells white so I could use the new connectors everywhere, but I could also produce a complementary set that is blue on white.
20211005_212403.jpg
20211005_212403.jpg (292.96 KiB) Viewed 5029 times
Unlike last time, I used a script to generate most of the SVG file. I did add the border by hand. I'll post the Python code a little later if I have time.

Update: Here's a python script I used to generate part of the SVG for laser cutting. You can see it's missing the boundary tiles and also won't cut cells completely unless they are surrounded. I added the rest by hand in Inkscape. I am not sure when I'll have a chance to update the script, but here it is if anyone wants to generate these laser cuts themselves.

Code: Select all

import json

TILE_TYPES = ['0001', '0011', '0101', '0111', '1111']

TILE_ROTATION = {}
for tile in TILE_TYPES:
  for i in range(len(tile)):
    TILE_ROTATION.setdefault(tile[i:] + tile[:i], (tile, (4 - i) % 4 * 90))

SVG_HEAD = '''
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
   xmlns:dc="http://purl.org/dc/elements/1.1/"
   xmlns:cc="http://creativecommons.org/ns#"
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   xmlns:svg="http://www.w3.org/2000/svg"
   xmlns="http://www.w3.org/2000/svg"
   width="420mm"
   height="297mm"
   viewBox="0 0 420 297"
   version="1.1"
   id="svg8">
  <defs
     id="defs2" />
  <metadata
     id="metadata5">
    <rdf:RDF>
      <cc:Work
         rdf:about="">
        <dc:format>image/svg+xml</dc:format>
        <dc:type
           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
        <dc:title></dc:title>
      </cc:Work>
    </rdf:RDF>
  </metadata>
  <g id="layer1">
'''.strip()

SVG_TAIL = '''
  </g>
</svg>
'''.strip()

PATH_FORMAT = '''
    <path
       id="%s"
       transform="translate(%s, %s) rotate(%s)"
       style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
       d="%s" />
'''.strip()

CUT_FORMAT = '''
    <path
       id="%s"
       style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
       d="%s" />
'''.strip()

PATH = {
  '1111': 'm -1.5126,12.5 c -1.91e-4,-0.95599 -0.775357,-1.73099 -1.73168,-1.73116 h -1.44642 c -0.216895,-0.93615 -0.586106,-1.81279 -1.062987,-2.56677 l 1.02267,-1.02267 c 1.555276,-1.6964 -0.752017,-4.00369 -2.448429,-2.44842 l -1.022668,1.02267 c -0.753984,-0.47688 -1.630618,-0.8461 -2.566772,-1.06299 l 2e-6,-1.44642 c -1.72e-4,-0.95632 -0.7751729,-1.73149 -1.7311639,-1.73168 m 24.9999989,-10e-6 c -0.955988,1.9e-4 -1.730991,0.77536 -1.731158,1.73168 v 1.44642 c -0.936158,0.2169 -1.812791,0.58611 -2.566775,1.06299 l -1.022668,-1.02267 c -1.696398,-1.55528 -4.003695,0.75202 -2.448421,2.44843 l 1.022669,1.02267 c -0.476881,0.75398 -0.846093,1.63061 -1.062991,2.56677 h -1.446415 c -0.956322,1.7e-4 -1.731489,0.77517 -1.731682,1.73116 m -9e-6,-25 c 1.91e-4,0.95599 0.775357,1.73099 1.731681,1.73116 h 1.446419 c 0.216896,0.93616 0.586106,1.81279 1.062988,2.56677 l -1.02267,1.02267 c -1.555276,1.6964 0.752016,4.0037 2.44843,2.44842 l 1.022668,-1.02267 c 0.753983,0.47689 1.630617,0.8461 2.566772,1.063 l -2e-6,1.44641 c 1.72e-4,0.95632 0.775173,1.73149 1.731164,1.73169 m -24.9999989,0 c 0.95599,-1.9e-4 1.7309919,-0.775361 1.7311589,-1.73168 v -1.44642 c 0.936157,-0.2169 1.812791,-0.58611 2.566774,-1.06299 l 1.022668,1.02267 c 1.696398,1.55528 4.003695,-0.75202 2.44842,-2.44843 l -1.02267,-1.02267 c 0.476883,-0.75398 0.846094,-1.63061 1.062991,-2.56677 h 1.446416 c 0.956323,-1.7e-4 1.731489,-0.77517 1.731682,-1.73116', 
  '0111': 'm 3.5,-12.5 c 0,0 -0.06374,1.69814 0.685232,3.44371 l 0.923977,-0.3824 c 0.178221,0.43012 0.393682,0.84396 0.643883,1.23662 l -1.022671,1.02268 c -1.555276,1.69641 0.752023,4.0037 2.44842,2.44868 l 1.023189,-1.02294 c 0.815144,0.50883 1.695945,0.86759 2.566249,1.06352 v 1.44641 c 1.8e-4,0.956299 0.775121,1.731489 1.731161,1.73169 m -25.000006,-1.99264 c 0.836348,-0.006 1.514211,-0.6839 1.514126,-1.52035 v -0.6413 c 0.761728,-0.17148 1.53307,-0.48538 2.246895,-0.93018 l 0.453199,0.45321 c 1.506958,1.36493 3.508079,-0.63618 2.142511,-2.14249 l -0.45321,-0.4532 c 0.444791,-0.71382 0.75869,-1.48517 0.93018,-2.24689 h 0.6413 c 0.836448,9e-5 1.514642,-0.67777 1.520349,-1.51413 m 16.004645,14.01153 c -0.956029,1.9e-4 -1.730978,0.77537 -1.731158,1.73168 v 1.44642 c -0.454541,0.10079 -0.899461,0.24096 -1.329632,0.4191 l -0.382928,-0.92346 c -2.205199,0.91357 -3.95717,2.66572 -4.870501,4.87102 l 0.92346,0.38292 c -0.17815,0.43018 -0.31831,0.8751 -0.4191,1.32963 h -1.44643 c -0.95631,1.8e-4 -1.731483,0.77514 -1.731674,1.73117 m -14.012032,-8.99944 c 0,0 1.698136,-0.0637 3.443711,0.68523 l -0.382399,0.92397 c 0.43012,0.17823 0.84396,0.39369 1.236622,0.64389 l 1.022668,-1.02267 c 1.696413,-1.55528 4.003707,0.75202 2.44869,2.44842 l -1.02294,1.02318 c 0.508825,0.81515 0.867582,1.69595 1.063513,2.56625 h 1.446417 c 0.956291,1.8e-4 1.731481,0.77513 1.731684,1.73117', 
  '0101': 'm -12.5,3.5 c 1.18195,1.3e-4 2.3523,0.23297 3.44423,0.68532 l -0.3824,0.92397 c 0.43012,0.17825 0.84395,0.3937 1.23661,0.64389 l 1.02268,-1.02319 c 1.6964,-1.555021 4.00371,0.75228 2.44869,2.44882 l -1.02294,1.0228 c 0.25033,0.39276 0.46609,0.80636 0.64443,1.23662 l 0.92397,-0.3824 c 0.45235,1.09194 0.68517,2.2623 0.68521,3.44414 m 7.00937,0 c 2.6e-4,-0.83661 0.67853,-1.51474 1.51515,-1.51465 h 0.6413 c 0.0882,-0.39802 0.21095,-0.78758 0.36691,-1.16427 l -0.92449,-0.38291 c 0.81194,-1.96016 2.36928,-3.5175 4.32944,-4.32945 l 0.38291,0.92449 c 0.37669,-0.15597 0.76625,-0.2787 1.16427,-0.36691 v -0.6413 c -9e-5,-0.83662 0.67805,-1.5149 1.51466,-1.51515 m 0,-7.00988 c -1.18193,-1.3e-4 -2.3523,-0.23297 -3.44423,-0.68532 l 0.3824,-0.92397 c -0.43012,-0.17825 -0.84394,-0.3937 -1.23661,-0.64389 l -1.02268,1.02319 c -1.6964,1.55502 -4.00369,-0.75228 -2.44869,-2.44882 l 1.02294,-1.0228 c -0.25033,-0.39276 -0.46607,-0.80636 -0.64441,-1.23662 l -0.92397,0.382399 c -0.45235,-1.091939 -0.68519,-2.262299 -0.68523,-3.444139 m -7.00938,0 c -2.6e-4,0.83661 -0.67854,1.51474 -1.51516,1.51465 h -0.6413 c -0.0882,0.39802 -0.21094,0.78758 -0.36689,1.16427 l 0.92447,0.38291 c -0.81194,1.96016 -2.36927,3.5175 -4.32943,4.32945 l -0.38291,-0.92449 c -0.37669,0.15597 -0.76625,0.2787 -1.16427,0.36691 v 0.6413 c 9e-5,0.83662 -0.67804,1.5149 -1.51465,1.51515', 
#  '0001': 'm 12.5,4.5 c -3.402711,0.0332 -6.103479,2.04311 -7.352011,4.93871 l 0.92398,0.38241 c -0.155879,0.37652 -0.278759,0.76638 -0.3669,1.16427 h -0.640789 c -0.83662,-9e-5 -1.514901,0.67804 -1.51516,1.51464 m 8.95088,-16.99996 c -1.050509,4e-5 -2.09075,-0.20682 -3.061321,-0.60876 l 0.382931,-0.92448 c -0.376499,-0.15598 -0.738931,-0.34431 -1.082619,-0.56328 l -0.45321,0.4532 c -1.50631,1.36557 -3.507412,-0.63555 -2.14249,-2.14251 l 0.453199,-0.45321 c -0.218969,-0.34369 -0.4073,-0.70612 -0.563279,-1.08262 l -0.924481,0.38293 c -0.401939,-0.97057 -0.608801,-2.01081 -0.608761,-3.06131 m -8.99994,0 c -0.0332,3.402699 -2.04311,6.10348 -4.93871,7.352 l -0.38241,-0.92398 c -0.376521,0.15588 -0.766379,0.27876 -1.16427,0.3669 v 0.64079 c 9e-5,0.83662 -0.67804,1.5149 -1.514639,1.51516 m 0,7.04395 c 4.605838,-5.29e-4 8.939316,3.59514 8.999448,9.00518', 
  '0001': 'm 12.5,4.5 c -3.40271,0.0332 -6.14802,2.04311 -7.39656,4.93871 l 0.92398,0.38241 c -0.15587,0.37652 -0.27875,0.76638 -0.3669,1.16427 h -0.60124 c -0.83662,-9e-5 -1.55445,0.67804 -1.5547,1.51464 m 8.99542,-16.99996 c -1.05051,4e-5 -2.09075,-0.20682 -3.06132,-0.60876 l 0.38293,-0.92448 c -0.3765,-0.15598 -0.73893,-0.34431 -1.08262,-0.56328 l -0.45321,0.4532 c -1.50631,1.36557 -3.50741,-0.63555 -2.14249,-2.14251 l 0.4532,-0.45321 c -0.21897,-0.34369 -0.4073,-0.70612 -0.56328,-1.08262 l -0.92448,0.38293 c -0.40194,-0.97057 -0.6088,-2.01081 -0.60876,-3.06131 m -8.99994,0 c -0.0332,3.402699 -2.04311,6.148005 -4.93871,7.396525 l -0.38241,-0.92398 c -0.37652,0.15588 -0.76638,0.27876 -1.16427,0.3669 v 0.64079 c 9e-5,0.83662 -0.67804,1.5149 -1.51464,1.51516 m 0,6.999425 c 4.60584,-5.29e-4 8.93932,3.59514 8.99945,9.00518',
  '0011': 'm 12.5,3.5 c -3.84769,0.0464 -6.8972,2.24419 -8.31524,5.55621 l 0.92397,0.3824 c -0.17812,0.43017 -0.31836,0.87508 -0.4191,1.32964 h -1.44694 c -0.9563,1.9e-4 -1.73146,0.77513 -1.73167,1.73116 m 10.98898,-16.00485 c -0.83689,-0.005 -1.51498,-0.68356 -1.51489,-1.52015 1e-5,-0.21375 0,-0.42755 0,-0.64131 -0.81752,-0.18539 -1.5665,-0.49011 -2.24586,-0.93017 l -0.45321,0.4532 c -1.50631,1.36557 -3.50741,-0.63555 -2.14249,-2.14251 l 0.45319,-0.4532 c -0.21889,-0.34355 -0.40736,-0.70577 -0.56327,-1.0821 l -0.92397,0.38292 c -0.40203,-0.97073 -0.60888,-2.01115 -0.60874,-3.06183 m -17.00077,16.00059 c 3.8477,0.0464 6.89721,2.24419 8.31525,5.55621 l -0.92397,0.3824 c 0.17812,0.43017 0.31836,0.87508 0.41909,1.32964 h 1.44695 c 0.9563,1.9e-4 1.73147,0.77513 1.73168,1.73116 m -10.989,-16.00485 c 0.83691,-0.005 1.51499,-0.68356 1.5149,-1.52015 -1e-5,-0.21375 -1e-5,-0.42755 -1e-5,-0.64131 0.81752,-0.18539 1.56651,-0.49011 2.24587,-0.93017 l 0.45321,0.4532 c 1.5063,1.36557 3.50741,-0.63555 2.14249,-2.14251 l -0.45319,-0.4532 c 0.21889,-0.34355 0.40734,-0.70577 0.56326,-1.0821 l 0.92397,0.38292 c 0.40203,-0.97073 0.60887,-2.01115 0.60875,-3.06183'
}

JIGSAW_CUT = "m -3.5,-12.5 h 2.348779 v -2.787939 h -0.695651 v -1.290354 c 0.03328,-1.059009 4.111292,-1.236928 4.167187,0.235643 v 1.054711 h -0.960535 v 2.787939 h 2.14022"
JIGSAW_CUT = "m 3.5,-12.5 -2.481144,0 v -2.444102 h 0.827943 v -1.63431 c -0.06569,-0.961777 -4.308405,-0.374402 -4.299479,0.579599 v 1.054711 h 0.960535 v 2.444102 l -2.007855,0"

LIVE_CELL_SEG = 5.9291
LIVE_CELL_AX = -11.535541
LIVE_CELL_3_CUT = "m %s,0 %s,0 c 6e-6,1.279634 -0.488184,2.558897 -1.464495,3.535202 1.95261,1.952621 5.118255,1.952609 7.070877,10e-7 -0.976303,-0.976312 -1.464505,-2.255561 -1.464504,-3.53518 l %s 0" 
LIVE_CELL_2_CUT = "m %s,0 h %s m 4.181362,0 h %s m %s,3.535529 c 1.952618,-1.952618 1.952619,-5.118443 8e-6,-7.071067 1.952618,-1.952619 5.118437,-1.952611 7.071063,3e-6 -1.952626,1.952622 -1.952609,5.118439 1.1e-5,7.071059 -1.952628,1.952633 -5.118458,1.952634 -7.071082,5e-6 z"

def windows(rows):
  return filter(lambda tup: tup[2] != '0000',
                [(i, j, rows[i][j] + rows[i][j + 1] + rows[i + 1][j + 1] + rows[i + 1][j])
                 for i in range(len(rows) - 1) for j in range(len(rows[0]) - 1)])

def cellvalue(rows, i, j):
  try:
   return int(rows[i][j])
  except IndexError:
   return 0

def neighborhoods(rows):
  res = []
  for i in range(len(rows)):
    for j in range(len(rows[i])):
      neighborhood = (cellvalue(rows, i - 1, j - 1),
                      cellvalue(rows, i - 1, j    ),
                      cellvalue(rows, i - 1, j + 1),
                      cellvalue(rows, i    , j + 1),
                      cellvalue(rows, i + 1, j + 1),
                      cellvalue(rows, i + 1, j    ),
                      cellvalue(rows, i + 1, j - 1),
                      cellvalue(rows, i    , j - 1))
      if sum(neighborhood):
        res.append((i, j, cellvalue(rows, i, j), neighborhood))
  return res

def match_neighbors(neighborhood, pattern):
  as_string = "".join(str(v) for v in neighborhood + neighborhood) 
  return as_string.index(pattern) if pattern in as_string else None 

def split_neighborhood(neighborhood):
  for i in range(4):
    shift = neighborhood[i:] + neighborhood[:i]
    yield i, (shift[:4], shift[4:])
  for i in range(8):
    shift = neighborhood[i:] + neighborhood[:i]
    yield i, (shift[:4], shift[4:6], shift[6:])
  for i in range(2):
    shift = neighborhood[i:] + neighborhood[:i]
    yield i, (shift[:2], shift[2:4], shift[4:6], shift[6:])

def crowding_tiles(split):
  return all(set([tup, tup[::-1]]).intersection([(0, 0, 1, 1), (0, 1), (1, 1)]) for tup in split[1])

def survive_tiles(split):
  return all(set([tup, tup[::-1]]).intersection([(0, 0, 0, 1), (0, 0, 1, 0), (0, 0, 1, 1), (0, 1, 0, 1)]) for tup in split[1])

def divide_cell(cell):
  tx, ty = (cell[1] + 0.5) * 25, (cell[0] + 0.5) * 25
  nghcells = cell[3] 
  if sum(nghcells) >= 4:
    split = list(filter(crowding_tiles, split_neighborhood(nghcells)))[0]

    # long split of crowded cell
    cellpos = split[0]
    rotation = 22.5 + 45 * cellpos
    start = -7
    length = 14
    if nghcells[cellpos - 1] + nghcells[cellpos] == 0:
      start -= 1
      length += 1
    if nghcells[(cellpos + 3) % 8] + nghcells[(cellpos + 4) % 8] == 0:
      length += 1
    print(PATH_FORMAT % ('cell_a_%d_%d_%d' % (cell[0], cell[1], cell[2]), tx, ty, rotation,
                                            'm %d 0 l %d 0' % (start, length)))

    # short (or double) split of crowded cell
    if len(split[1]) >= 3:
      cellpos = (split[0] + 6) % 8
      rotation = 22.5 + 45 * cellpos
      start = -7
      length = 7
      if nghcells[cellpos - 1] + nghcells[cellpos] == 0:
        start -= 1
        length += 1
      if len(split[1]) == 4:
        length += 7
        if nghcells[(cellpos + 3) % 8] + nghcells[(cellpos + 4) % 8] == 0:
          length += 1
      print(PATH_FORMAT % ('cell_b_%d_%d_%d' % (cell[0], cell[1], cell[2]), tx, ty, rotation,
                                              'm %d 0 l %d 0' % (start, length)))

  elif cell[2] and sum(nghcells) in [2,3]:
    split = list(filter(survive_tiles, split_neighborhood(nghcells)))[0]

    # cell split
    cellpos = split[0]
    if sum(split[1][1]) == 2:
      cellpos = (cellpos + 4) % 8
    rotation = 22.5 + 45 * cellpos
    start = -8
    length1 = LIVE_CELL_SEG
    if nghcells[cellpos - 1] + nghcells[cellpos] == 0:
      start -= 1
      length1 += 1
    length2 = LIVE_CELL_SEG
    ax = LIVE_CELL_AX
    if nghcells[(cellpos + 3) % 8] + nghcells[(cellpos + 4) % 8] == 0:
      length2 += 1
      ax -= 1
    path = (LIVE_CELL_2_CUT % (start, length1, length2, ax) if sum(nghcells) == 2
            else LIVE_CELL_3_CUT % (start, length1, length2))
    print(PATH_FORMAT % ('cell_%d_%d_%d' % (cell[0], cell[1], cell[2]), tx, ty, rotation, path))


ROTATION = {
  0: lambda x, y: (x, y),
  1: lambda x, y: (-y, x),
  2: lambda x, y: (-x, -y),
  3: lambda x, y: (y, -x)
}

CUTS = {
  '0': {
    True: (-4.5, 4.5),
    False: (-3.5, 3.5),
  },
  '1': {
    True: (-1.5126, 1.5126),
    False: (-3.5, 3.5),
  }
}


PATTERN = '''
...........
....**.....
....*.*.**.
......*.**.
..*...*....
.*.*.**....
..*........
...........
'''

rows = PATTERN.replace('.', '0').replace('*', '1').strip().split('\n')

cut_ids = set()
print(SVG_HEAD)
for i, j, tile in windows(rows):
  normtile, rotation = TILE_ROTATION[tile]
  tx, ty = (j + 1) * 25, (i + 1) * 25
  print(PATH_FORMAT % (tile + '_%d_%d' % (i, j), tx, ty, rotation, PATH[normtile]))

  for k in range(len(tile)):
    from_val = tile[k] 
    to_val = tile[(k + 1) % 4] 
    cut_from, cut_to = CUTS[from_val][from_val == to_val]
    mx, my = ROTATION[k](cut_from, -12.5)
    lx, ly = ROTATION[k](cut_to - cut_from, 0)
    cut_id = 'cut_%d_%d_%d' % ((i + 1) if k == 2 else i, (j + 1) if k == 1 else j, 3 * (k % 2))
    if from_val == '0' and to_val == '1':
      print(PATH_FORMAT % (cut_id, tx, ty, k * 90, JIGSAW_CUT))
    elif cut_id not in cut_ids and from_val == to_val:
      cut_ids.add(cut_id)
      print(CUT_FORMAT % (cut_id, "m %f %f l %f %f") % (tx + mx, ty + my, lx, ly))

for cell in neighborhoods(rows):
  divide_cell(cell)

print(SVG_TAIL)

User avatar
pcallahan
Posts: 845
Joined: April 26th, 2013, 1:04 pm

Re: Realizing still life constraints as a planar tiling

Post by pcallahan » October 9th, 2021, 3:30 pm

For fun (because the rest of this is so serious) I decided to take a picture of the acrylic pieces next to a printout of what I expected them to look like (2D) along with a comparison lego piece.
20211009_122007.jpg
20211009_122007.jpg (95.02 KiB) Viewed 4912 times
I'm still working on what to do about kerf and the best connector shapes, but I think this looks pretty good already. If anyone else is crazy enough to want actual acrylic pieces, I'd be happy to arrange a big order, at cost (though it may be hard to get the pieces to you). The price comes down a lot with size of order. I can also make SVG files available to anyone who wants to do this themselves.

Update: I put together still lifes up to 6 cells with tiles. This is not purely for fun. I wanted to get a sense of whether this could be a viable puzzle for someone less obsessed than I am. These weren't too hard to assemble, but I think the pieces need to fit tighter before most people would be willing to do it. I also think it's unlikely someone would work on it as a puzzle without knowing the result has to be a still life. It would certainly be interesting to see if someone who did not know could figure this out just by putting pieces together.
Screen Shot 2021-10-10 at 11.07.45 PM.png
Screen Shot 2021-10-10 at 11.07.45 PM.png (1.92 MiB) Viewed 4882 times
Screen Shot 2021-10-10 at 11.12.21 PM.png
Screen Shot 2021-10-10 at 11.12.21 PM.png (2.68 MiB) Viewed 4882 times
Update 2: While building "barge", I came close to running out of loneliness cells (dead with <=2 live neighbors) and I also have more experience with laser cut acrylic now, which can be cut very small and preserve features (like the overcrowding tiles) I think instead of 5 whole tiles, it would be better to use calcyman's split into 4 tiles from viewtopic.php?f=7&t=2188#p30926 It adds to some assembly work, but besides reducing tile count, it makes it possible to represent 0 neighbors as well as increasing overall flexibility (keeping in mind that the goal is not just to represent neighborhoods but multisets of neighborhoods with a small set of tiles). If you take 4 copies of the inner piece from border tiles, you can construct the 2x2 window of empty cells. This makes it possible to tile the plane with empty cells if you so choose.

User avatar
pcallahan
Posts: 845
Joined: April 26th, 2013, 1:04 pm

Re: Realizing still life constraints as a planar tiling

Post by pcallahan » November 22nd, 2021, 2:30 pm

benetnasch85 wrote:
September 7th, 2021, 12:58 am
Another way to tighten up the boundary would be to indent the boundary pieces on both sides and link them with asymmetric "axe heads" that can be cut separately in a slightly larger size.
I am not sure why it never occurred to me, but this idea would also work on the internal tiles, and would have the added benefit of bringing back flip symmetry to pieces that become unrecognizable (to me anyway) when I add the jigsaw connections. It would require an extra tile, cut separately as stated above. The pieces could be made to lock together very securely. Here's the idea:
Screen Shot 2021-11-22 at 10.22.11 AM.png
Screen Shot 2021-11-22 at 10.22.11 AM.png (325.02 KiB) Viewed 4506 times
The connecting tiles could be made simpler (e.g. a rectangular U shape) so they can be cut together, but this is just the quickest example I could come up with without too much extra design work.

A real test will have to wait for a new order, but I think this is promising. I am currently waiting for kerf-corrected boundary pieces, keeping my fingers crossed that they will really connect the way I want.

User avatar
pcallahan
Posts: 845
Joined: April 26th, 2013, 1:04 pm

Re: Realizing still life constraints as a planar tiling

Post by pcallahan » December 2nd, 2021, 12:06 am

I got the kerf-corrected boundary pieces today. I should have added a little more compensating thickness. I was cautious and corrected for 0.125mm of kerf, but I probably could have gone up to 0.15mm at least. So the pieces are still a little jiggly, and they don't hold together by friction when lifted. They're still a great improvement over the original. I have somewhat mixed feelings about the clear boundary. I think it looks better on the eater, maybe because it's against a white background matching empty cells.
20211201_192903.jpg
20211201_192903.jpg (723.79 KiB) Viewed 4363 times
20211201_192323.jpg
20211201_192323.jpg (240.36 KiB) Viewed 4363 times

User avatar
pcallahan
Posts: 845
Joined: April 26th, 2013, 1:04 pm

Re: Realizing still life constraints as a planar tiling

Post by pcallahan » January 17th, 2022, 8:38 pm

If you don't know, Cricut is a popular computer-controlled die cutter normally used for lightweight crafting applications like making cards, decals, and iron-ons. The "Maker" was introduced a few years back and includes a knife blade that can cut thicker materials. Cricut Makers have come down in price recently, and I finally got one, thinking I could save myself time (if not money) on laser cuts, though I can't do all the things I'd like with it.

I finally got around to cutting out still life tiles. I'm not using the knife blade for this. It can cut mat board but it's slow. I decided first to try the "deep cut" blade on 2mm eva foam (like for kids' crafts). This is hard to get right because the blade squashes the foam when doing tight curves and details. It works better if I double the size of the tile (pink pieces below; pink because I have a variety pack and I am practicing with colors I'm less interested in using).

I had a surprising success (which prompted me to post) using cardboard from a Cheerios box. This is about 0.7mm thick and requires 3 passes of the deep cut blade to cut through. But It preserves the details at the original size of these pieces. They actually hold pretty well as jigsaw pieces, since they don't burn away 0.2mm around the cut. It's a little labor intensive, but I might be able to make very usable pieces by gluing them 3 layers thick. It lacks the "wow" of shiny acrylic, but it's nice to be able to make these on a home device (laser cutters are still quite expensive and I don't have a 3D printer).
20220117_161409.jpg
20220117_161409.jpg (565.54 KiB) Viewed 3446 times

User avatar
pcallahan
Posts: 845
Joined: April 26th, 2013, 1:04 pm

Re: Realizing still life constraints as a planar tiling

Post by pcallahan » February 6th, 2022, 6:18 pm

I finally had a chance to make all the tiles for an eater using a cereal box. The cuts are precise enough and the pieces hold better than you'd think. 0.7mm is thin but you don't burn away the material as you would with a laser. Commercial jigsaw puzzles are about 2mm thick, which is a little too much to cut easily on a Cricut. I could glue triple layers, but that's a lot of work. (I just noticed I said all that in the last posting. Anyway, here's what I did.)

Leftover cereal box material:
20220206_122259.jpg
20220206_122259.jpg (552.43 KiB) Viewed 3092 times
Pieces partly assembled:
20220206_122247.jpg
20220206_122247.jpg (197.65 KiB) Viewed 3092 times
Final assembly but without live cells. I will need to color them to make them visible.
20220206_123258.jpg
20220206_123258.jpg (383.07 KiB) Viewed 3092 times

User avatar
pcallahan
Posts: 845
Joined: April 26th, 2013, 1:04 pm

Re: Realizing still life constraints as a planar tiling

Post by pcallahan » February 20th, 2022, 5:22 pm

Another week and trying to push the limits of what I can do using a Cricut. I'm not too happy with how it cuts anything thicker than cereal box cardboard. While it can cut up to 2.4mm thick in theory, it requires multiple cuts and I also think the knife blade is not good with the tight corners in these tiles.

However, it is really good at cutting 0.3mm poster board with the fine point blade, and I decided to use this to cut layers that can be combined into a mold for polymer clay. I started with Sculpey III, somewhat randomly, and it turned out to be a poor choice because it is brittle and snaps easily. Actually, generic polymer clay works better for small pieces since it is flexible. I also made a sample piece with Sculpey Premo, which costs the same and is bendable and tougher overall. But for this project, I used:
20220215_091733.jpg
20220215_091733.jpg (435.41 KiB) Viewed 3007 times
Here's one of my molds after baking, and an assembled live cell.
20220219_115505.jpg
20220219_115505.jpg (218.95 KiB) Viewed 3007 times
Instead of trying to glue the layers into a single piece I found that it's more effective to align them like playing cards before filling the mold, and peel them off after baking. Sometimes they tear, though they usually don't. In fact, cutting the mold is the fastest part of this process and uses cardboard that is cheaper than the same volume of polymer clay. (But I reuse molds when I can).

The live cell pieces really hold together well compared to acrylic. One reason is there is no lost material, but an unexpected benefit of using a layered mold is that the sides of the pieces are ridged. In fact, the fit is a little too tight and I may try to compensate with the mold boundaries if I do this again. The white powder on the piece is probably residue from white clay on my fingers. It's not very noticeable except in the closeup.

I eventually ran out of the white Sculpey and completed the project with generic clay, hence the color variation. The result looks crude compared to acrylic, but my crafting is getting better. I am thinking of eliminating the jigsaw connectors entirely to restore symmetry and make the molds easier to fill.

Here are two pictures of the completed project. The left side shows the boundary tiles, which are hard to align. The right side replaces them with a custom-cut piece of mat board. Since the boundary is (IMO) the least interesting part of this tiling, it may be a reasonable approach, particularly after eliminating internal jigsaw connections.
withmat.png
withmat.png (1.05 MiB) Viewed 2978 times

Post Reply