Skip to content

Instantly share code, notes, and snippets.

@nst
Created September 16, 2021 20:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nst/7f1da4b9b5c2366868624096fc5670e5 to your computer and use it in GitHub Desktop.
Save nst/7f1da4b9b5c2366868624096fc5670e5 to your computer and use it in GitHub Desktop.
# Nicolas Seriot
# 2021-09-16
# Thread: https://twitter.com/nst021/status/1437889678947110912
# Typical output: https://seriot.ch/visualization/iso3.png
import cairo
import random
import numpy as np
MARGIN = 50
X_MAX, Y_MAX, Z_MAX = 12, 16, 5 # space size
DW, DH = 60, 30 # diamond size
DW2, DH2 = int(DW/2), int(DH/2)
N = 300
def draw_surface(c, points, color):
c.save()
c.set_source_rgb(*color)
c.set_line_width(1)
[c.line_to(*p) for p in points]
c.close_path()
c.fill_preserve()
c.set_source_rgb(0,0,0)
c.set_line_join(cairo.LINE_CAP_SQUARE) # ok aa
c.stroke()
c.restore()
def draw_grid(c):
for x in range(X_MAX):
for y in range(Y_MAX):
draw_cube(c, x, y, 0, flat=True)
def model_to_canvas(x, y):
o_x = DW2 * Y_MAX
o_y = DH2
return (o_x + DW2*(x-y), o_y + DH2*(x+y))
def draw_cube(c, x, y, z, flat=False):
print("--", x, y, z)
x, y = model_to_canvas(x, y)
c.save()
c.translate(x, y)
"""
5
2 6
3 - DH
1 7
4
| z_offset
"""
z_offset = DH * z
p1 = (0, z_offset + DH2)
p2 = (0, z_offset + DH2 + DH)
p3 = (DW2, z_offset + DH)
p4 = (DW2, z_offset + 0)
p5 = (DW2, z_offset + 2*DH)
p6 = (DW, z_offset + DH2 + DH)
p7 = (DW, z_offset + DH2)
#COLOR_RIGHT = (0.5,0.5,0.5)
#COLOR_TOP = (1,1,1)
#COLOR_LEFT = (0,0,0)
z_ratio = 0.4 + z*0.6/Z_MAX
COLOR_TOP = (1 * z_ratio, 0.5 * z_ratio, 0.5 * z_ratio)
COLOR_LEFT = (0.6 * z_ratio, 0, 0)
COLOR_RIGHT = (1 * z_ratio, 0, 0)
if flat:
draw_surface(c, [p1, p3, p7, p4], (1,1,1))
else:
draw_surface(c, [p2, p5, p6, p3], COLOR_TOP)
draw_surface(c, [p1, p2, p3, p4], COLOR_LEFT)
draw_surface(c, [p3, p6, p7, p4], COLOR_RIGHT)
c.restore()
def fill_model(m):
for _ in range(N):
x = random.randint(0, X_MAX-1)
y = random.randint(0, Y_MAX-1)
z = random.randint(0, Z_MAX-1)
m[x][y][z] = True
def draw_model(c, m):
X,Y,Z = m.shape
for x in range(X)[::-1]:
for y in range(Y)[::-1]:
for z in range(Z_MAX):
if m[x][y][z]:
draw_cube(c,x,y,z)
m = np.full((X_MAX, Y_MAX, Z_MAX), False, dtype=bool)
fill_model(m)
#m[2][3][0] = True
#m[2][3][1] = True
#m[3][3][0] = True
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32,
DW + (X_MAX+Y_MAX)*DW2 + MARGIN*2,
DH + (X_MAX+Y_MAX)*DH2 + Z_MAX*DH + MARGIN*2)
c = cairo.Context(surface)
cm = cairo.Matrix(yy=-1, y0=surface.get_height())
c.transform(cm)
c.translate(MARGIN, MARGIN)
c.set_antialias(cairo.ANTIALIAS_NONE)
#background
c.set_source_rgb(1,1,1)
c.paint()
#pen
c.set_source_rgb(0,0,0)
c.set_line_width(1)
draw_grid(c)
draw_model(c, m)
#draw_cube(c, 1, 0, 0)
surface.write_to_png("iso3.png")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment