Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import random
- class Coordinates:
- def __init__(self, x, y):
- self.x = x
- self.y = y
- class Obstacle:
- def __init__(self, x, y, radius):
- self.center = Coordinates(x, y)
- self.radius = radius
- class Disturbance:
- def __init__(self, x, y, dx, dy):
- self.start = Coordinates(x, y)
- self.size = Coordinates(dx, dy)
- def create_particles_field(field_size, density):
- random.seed()
- return [[int(0 < x < field_size.x - 1 and 0 < y < field_size.y - 1 and random.random() > density)
- for x in range(field_size.x)] for y in range(field_size.y)]
- def create_bounds_field(field_size):
- return [[int((x == 0 or x == field_size.x - 1) or (y == 0 or y == field_size.y - 1))
- for x in range(field_size.x)] for y in range(field_size.y)]
- def circle_coord_generator(size, center, radius):
- radius -= 1
- for x in range(max(center - radius, 1), min(center + radius, size - 1) + 1):
- yield x
- def fill_obstacle(particles_field, bounds_field, field_size, obstacle):
- sqr_radius = obstacle.radius**2
- for y in circle_coord_generator(field_size.y - 1, obstacle.center.y, obstacle.radius):
- for x in circle_coord_generator(field_size.x - 1, obstacle.center.x, obstacle.radius):
- if (x - obstacle.center.x)**2 + (y - obstacle.center.y)**2 <= sqr_radius:
- particles_field[y][x] = 0
- bounds_field[y][x] = 1
- def fill_fields(field_size, density, obstacle):
- particles_field = create_particles_field(field_size, density)
- bounds_field = create_bounds_field(field_size)
- fill_obstacle(particles_field, bounds_field, field_size, obstacle)
- return particles_field, bounds_field
- def calc_block_amount(size, is_odd):
- return size // 2 + is_odd
- def get_rotated_diag(block):
- main_diagonal = [[1, 0], [0, 1]]
- anti_diagonal = [[0, 1], [1, 0]]
- return {
- main_diagonal: anti_diagonal,
- anti_diagonal: main_diagonal,
- }.get(block, None)
- def copy_block(field, block, actual_coord):
- for y in range(2):
- for x in range(2):
- field[actual_coord.y + y][actual_coord.x + x] = block[y][x]
- def multi_dimensional_slice(arr, start_x, count_x, start_y, count_y):
- return [[arr[y][x] for x in range(start_x, start_x + count_x)] for y in range(start_y, start_y + count_y)]
- def multi_dimensional_sum(arr, start_x, count_x, start_y, count_y):
- return sum(arr[y][x] for x in range(start_x, start_x + count_x) for y in range(start_y, start_y + count_y))
- def step(particles_field, bounds_field, field_size, is_odd):
- is_odd = int(is_odd)
- blocks_amount = Coordinates(calc_block_amount(field_size.x, is_odd), calc_block_amount(field_size.y, is_odd))
- for y in range(len(blocks_amount.y)):
- actual_coord = Coordinates(0, y * 2 + is_odd)
- for x in range(len(blocks_amount.x)):
- actual_coord.x = x * 2 + is_odd
- bounds_sum = multi_dimensional_sum(bounds_field, actual_coord.x, 2, actual_coord.y, 2)
- if bounds_sum == 0:
- block = multi_dimensional_slice(particles_field, actual_coord.x, 2, actual_coord.y, 2)
- rotated_diag = get_rotated_diag(block)
- if rotated_diag:
- copy_block(particles_field, rotated_diag, actual_coord)
- else:
- flat_block = [block[y][x] for x in range(2) for y in range(2)]
- flat_block.reverse()
- block = [flat_block[y * 2:y * 2 + 1] for y in range(2)]
- copy_block(particles_field, block, actual_coord)
- def averaging(particles_field, field_size, scale):
- return [[multi_dimensional_sum(particles_field, x * scale, scale, y * scale, scale)
- for x in range(field_size.x // scale)] for y in range(field_size.y // scale)]
- def disturb_coord_gen(size, start, length):
- for x in range(max(start, 1), min(start + length, size - 1)):
- yield x
- def create_disturbance(particles_field, field_size, disturbance):
- for y in disturb_coord_gen(field_size.y, disturbance.start.y, disturbance.size.y):
- for x in disturb_coord_gen(field_size.x, disturbance.start.x, disturbance.size.x):
- particles_field[y][x] = 1
- def run_simulation(particles_field, bounds_field, field_size, disturbance, scale, stop_cond, is_disturbance):
- epochs_amount = 0
- while not stop_cond:
- step(particles_field, bounds_field, field_size, True)
- if is_disturbance:
- create_disturbance(particles_field, field_size, disturbance)
- averaged = averaging(particles_field, field_size, scale)
- epochs_amount += 1
- print_field(averaged)
- # DEBUG
- def print_field(field):
- print('\t[' + ', '.join(str(x) for x in range(len(field[0]))) + ']')
- for y in range(len(field)):
- print(str(y) + '\t' + str(field[y]))
- print('\n')
- def main():
- field_size = Coordinates(*map(int, input('Введите размеры плоскости: ').split()))
- density = float(input('Введите плотность распределения: '))
- obstacle = Obstacle(*map(int, input('Введите координаты препятсвия и его радиус: ').split()))
- disturbance = Disturbance(*map(int, input('Введите начальные координаты возмущения и его размеры: ').split()))
- scale = int(input('Введите усреднение: '))
- particles_field, bounds_field = fill_fields(field_size, density, obstacle)
- run_simulation(particles_field, bounds_field, field_size, disturbance, scale, False, 10)
- main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement