-
Notifications
You must be signed in to change notification settings - Fork 0
/
sandpileModel_v0_0_1.py
121 lines (113 loc) · 4 KB
/
sandpileModel_v0_0_1.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
import array
class bmp:
""" bmp data structure """
def __init__(self, w=1080, h=1920):
self.w = w
self.h = h
def calc_data_size (self):
if((self.w*3)%4 == 0):
self.dataSize = self.w * 3 * self.h
else:
self.dataSize = (((self.w * 3) // 4 + 1) * 4) * self.h
self.fileSize = self.dataSize + 54
def conv2byte(self, l, num, len):
tmp = num
for i in range(len):
l.append(tmp & 0x000000ff)
tmp >>= 8
def gen_bmp_header (self):
self.calc_data_size();
self.bmp_header = [0x42, 0x4d]
self.conv2byte(self.bmp_header, self.fileSize, 4) #file size
self.conv2byte(self.bmp_header, 0, 2)
self.conv2byte(self.bmp_header, 0, 2)
self.conv2byte(self.bmp_header, 54, 4) #rgb data offset
self.conv2byte(self.bmp_header, 40, 4) #info block size
self.conv2byte(self.bmp_header, self.w, 4)
self.conv2byte(self.bmp_header, self.h, 4)
self.conv2byte(self.bmp_header, 1, 2)
self.conv2byte(self.bmp_header, 24, 2) #888
self.conv2byte(self.bmp_header, 0, 4) #no compression
self.conv2byte(self.bmp_header, self.dataSize, 4) #rgb data size
self.conv2byte(self.bmp_header, 0, 4)
self.conv2byte(self.bmp_header, 0, 4)
self.conv2byte(self.bmp_header, 0, 4)
self.conv2byte(self.bmp_header, 0, 4)
def print_bmp_header (self):
length = len(self.bmp_header)
for i in range(length):
print("{:0>2x}".format(self.bmp_header[i]), end=' ')
if i%16 == 15:
print('')
print('')
def paint_bgcolor(self, color=0xffffff):
## self.rgbData = []
## for r in range(self.h):
## self.rgbDataRow = []
## for c in range(self.w):
## self.rgbDataRow.append(color)
## self.rgbData.append(self.rgbDataRow)
rgbDataRow = [color] * (self.w+1)
self.rgbData = [rgbDataRow.copy() for i in range(self.h)]
def set_at(self,x, y, color):
self.rgbData[y][x] = color
def paint_line(self, x1, y1, x2, y2, color):
k = (y2 - y1) / (x2 - x1)
for x in range(x1, x2+1):
y = int(k * (x - x1) + y1)
self.rgbData[y][x] = color
def paint_rect(self, x1, y1, w, h, color):
for x in range(x1, x1+w):
for y in range(y1, y1+h):
self.rgbData[y][x] = color
def save_image(self, name="save.bmp"):
f = open(name, 'wb')
#write bmp header
f.write(array.array('B', self.bmp_header).tobytes())
#write rgb data
zeroBytes = self.dataSize // self.h - self.w * 3
for r in range(self.h):
l = []
for i in range(len(self.rgbData[r])):
p = self.rgbData[r][i]
l.append(p & 0x0000ff)
p >>= 8
l.append(p & 0x0000ff)
p >>= 8
l.append(p & 0x0000ff)
f.write(array.array('B', l).tobytes())
for i in range(zeroBytes):
f.write(bytes(0x00))
f.close()
sand = list([0] * 2003 for i in range(2003))
final = ''
image = bmp(2003, 2003)
image.gen_bmp_header()
image.print_bmp_header()
image.paint_bgcolor(0x000000)
stack = []
def update(i, j):
if i == 0 or i == 2002 or j == 0 or j == 2002:
sand[i][j] = 0
elif sand[i][j] >= 4:
q = sand[i][j] // 4
sand[i + 1][j] += q
sand[i - 1][j] += q
sand[i][j + 1] += q
sand[i][j - 1] += q
sand[i][j] %= 4
stack.append((i + 1, j))
stack.append((i - 1, j))
stack.append((i, j + 1))
stack.append((i, j - 1))
for i in range(40000):
sand[1001][1001] += 1
stack.append((1001, 1001))
while stack:
update(*stack.pop())
if i%100==0:print(i)
for i in range(1, 2003):
for j in range(1, 2003):
image.set_at(i, j, [0x0000ff, 0x00ffff, 0x00ff00, 0xff0000][sand[i][j]])
if i%100==0:print(i)
image.save_image('sand.bmp')