Alexandre B A Villares 2023-11-24 10:43:39 -03:00
rodzic cedfb827cf
commit 66e3dfdb4a
3 zmienionych plików z 182 dodań i 1 usunięć

Wyświetl plik

@ -20,7 +20,7 @@ def draw():
#z = np.full(50, py5.frame_count * s)
d = 128 + 128 * py5.os_noise(xgrid * s, ygrid * s, py5.frame_count * s)
my_box(xgrid, ygrid, -200 + d / 2, 10, 10, d)
#print(py5.frame_count)
py5.window_title(f'{py5.get_frame_rate():.1f}')
@np.vectorize
@ -31,4 +31,9 @@ def my_box(x, y, z, *args):
py5.box(*args)
py5.pop()
def key_pressed():
py5.print_line_profiler_stats()
py5.profile_draw()
py5.run_sketch()

Wyświetl plik

@ -152,5 +152,8 @@ def draw():
py5.vertices(triangles)
py5.window_title(f'{py5.get_frame_rate():.1f}')
def key_pressed():
py5.print_line_profiler_stats()
py5.profile_draw()
py5.run_sketch(block=False)

Wyświetl plik

@ -0,0 +1,173 @@
# -----------------------------------------------------------------------------
# Copyright (2017) Alexandre B A Villares - BSD license
# Numpy flocking with py5
#
# Based on the boids flocking example from "From Pytnon to Numpy"
# Copyright (2017) Nicolas P. Rougier - BSD license
# More information at https://github.com/rougier/numpy-book
# -----------------------------------------------------------------------------
import numpy as np
import py5
class Flock:
def __init__(self, count, width, height):
self.width = width
self.height = height
self.min_velocity = 0.5
self.max_velocity = 2.0
self.max_acceleration = 0.03
self.velocity = np.zeros((count, 2), dtype=np.float32)
self.position = np.zeros((count, 2), dtype=np.float32)
angle = np.random.uniform(0, 2*np.pi, count)
self.velocity[:, 0] = np.cos(angle)
self.velocity[:, 1] = np.sin(angle)
angle = np.random.uniform(0, 2*np.pi, count)
radius = min(width, height)/2*np.random.uniform(0, 1, count)
self.position[:, 0] = width/2 + np.cos(angle)*radius
self.position[:, 1] = height/2 + np.sin(angle)*radius
def setup():
global flock
py5.size(640, 640)
py5.no_stroke()
N = 500
flock = Flock(N, py5.width, py5.height)
def draw():
py5.background(0)
###
position = flock.position
velocity = flock.velocity
min_velocity = flock.min_velocity
max_velocity = flock.max_velocity
max_acceleration = flock.max_acceleration
n = len(position)
dx = np.subtract.outer(position[:, 0], position[:, 0])
dy = np.subtract.outer(position[:, 1], position[:, 1])
distance = np.hypot(dx, dy)
#print(distance.shape)
# Compute common distance masks
mask_0 = (distance > 0)
mask_1 = (distance < 25)
mask_2 = (distance < 50)
mask_1 *= mask_0
mask_2 *= mask_0
mask_3 = mask_2
mask_1_count = np.maximum(mask_1.sum(axis=1), 1)
mask_2_count = np.maximum(mask_2.sum(axis=1), 1)
mask_3_count = mask_2_count
flock.count = mask_2_count
# Separation
mask, count = mask_1, mask_1_count
target = np.dstack((dx, dy))
target = np.divide(target, distance.reshape(n, n, 1)**2, out=target,
where=distance.reshape(n, n, 1) != 0)
steer = (target*mask.reshape(n, n, 1)).sum(axis=1)/count.reshape(n, 1)
norm = np.sqrt((steer*steer).sum(axis=1)).reshape(n, 1)
steer = max_velocity*np.divide(steer, norm, out=steer,
where=norm != 0)
steer -= velocity
# Limit acceleration
norm = np.sqrt((steer*steer).sum(axis=1)).reshape(n, 1)
steer = np.multiply(steer, max_acceleration/norm, out=steer,
where=norm > max_acceleration)
separation = steer
# Alignment
# ---------------------------------------------------------------------
# Compute target
mask, count = mask_2, mask_2_count
target = np.dot(mask, velocity)/count.reshape(n, 1)
# Compute steering
norm = np.sqrt((target*target).sum(axis=1)).reshape(n, 1)
target = max_velocity * np.divide(target, norm, out=target,
where=norm != 0)
steer = target - velocity
# Limit acceleration
norm = np.sqrt((steer*steer).sum(axis=1)).reshape(n, 1)
steer = np.multiply(steer, max_acceleration/norm, out=steer,
where=norm > max_acceleration)
alignment = steer
# Cohesion
# ---------------------------------------------------------------------
# Compute target
mask, count = mask_3, mask_3_count
target = np.dot(mask, position)/count.reshape(n, 1)
# Compute steering
desired = target - position
norm = np.sqrt((desired*desired).sum(axis=1)).reshape(n, 1)
desired *= max_velocity / norm
steer = desired - velocity
# Limit acceleration
norm = np.sqrt((steer*steer).sum(axis=1)).reshape(n, 1)
steer = np.multiply(steer, max_acceleration/norm, out=steer,
where=norm > max_acceleration)
cohesion = steer
# ---------------------------------------------------------------------
acceleration = 1.5 * separation + alignment + cohesion
velocity += acceleration
norm = np.sqrt((velocity*velocity).sum(axis=1)).reshape(n, 1)
velocity = np.multiply(velocity, max_velocity/norm, out=velocity,
where=norm > max_velocity)
velocity = np.multiply(velocity, min_velocity/norm, out=velocity,
where=norm < min_velocity)
position += velocity
# Wraparound
position += (flock.width, flock.height)
position %= (flock.width, flock.height)
###
red_mask = flock.count > 30
draw_boids(flock, red_mask,'red')
magenta_mask = (20 < flock.count) * (flock.count <= 30)
draw_boids(flock, magenta_mask,'magenta')
blue_mask = flock.count <= 20
draw_boids(flock, blue_mask, 'blue')
def draw_boids(flock, mask, fill_color):
position = flock.position[mask]
velocity = flock.velocity[mask]
boid_length = 10
norm_vel = velocity / np.linalg.norm(velocity,axis=1, keepdims=True)
heading = norm_vel * boid_length
perpend_a = norm_vel[:,::-1].copy() * (boid_length / 3)
perpend_a[:, 0] = -perpend_a[:, 0]
perpend_b = norm_vel[:,::-1].copy() * (boid_length / 3)
perpend_b[:, 1] = -perpend_b[:, 1]
# the arrow points
right_points = position + perpend_a
left_points = position + perpend_b
head_points = position + heading
triangles = np.hstack(
(left_points, right_points, head_points)).reshape(-1, 2)
triple_count = np.hstack(
(flock.count, flock.count, flock.count)).reshape(-1, 1)
py5.fill(fill_color)
with py5.begin_shape(py5.TRIANGLES):
py5.vertices(triangles)
py5.window_title(f'{py5.get_frame_rate():.1f}')
def key_pressed():
print(flock.count.shape, 'flock.count')
print((flock.count < 50).shape, 'flock.count < 50')
py5.print_line_profiler_stats()
# print(triple_count.shape, 'triple_count')
#print(triangles.shape, 'triangles')
py5.profile_draw()
py5.run_sketch(block=False)