Skip to content

Commit f5631da

Browse files
authored
Update boid_flockers example include flight direction (#2696)
I updated boid_flockers so that the direction of movement of agents is shown in the simulation. I did this by changing the marker to caret-down (a triangle with a larger base so that the direction of motion is not ambiguous) and then rotating the marker according to the direction of motion of the agent.
1 parent 44308a8 commit f5631da

File tree

3 files changed

+30
-2
lines changed

3 files changed

+30
-2
lines changed

mesa/examples/basic/boid_flockers/agents.py

+1
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ def __init__(
5858
self.separate_factor = separate
5959
self.match_factor = match
6060
self.neighbors = []
61+
self.angle = 0.0 # represents the angle at which the boid is moving
6162

6263
def step(self):
6364
"""Get the Boid's neighbors, compute the new vector, and move accordingly."""

mesa/examples/basic/boid_flockers/app.py

+17-2
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,34 @@
11
import os
22
import sys
33

4+
from matplotlib.markers import MarkerStyle
5+
46
sys.path.insert(0, os.path.abspath("../../../.."))
57

68
from mesa.examples.basic.boid_flockers.model import BoidFlockers
79
from mesa.visualization import Slider, SolaraViz, make_space_component
810

11+
# Pre-compute markers for different angles (e.g., every 10 degrees)
12+
MARKER_CACHE = {}
13+
for angle in range(0, 360, 10):
14+
marker = MarkerStyle(10)
15+
marker._transform = marker.get_transform().rotate_deg(angle)
16+
MARKER_CACHE[angle] = marker
17+
918

1019
def boid_draw(agent):
1120
neighbors = len(agent.neighbors)
1221

22+
# Calculate the angle
23+
deg = agent.angle
24+
# Round to nearest 10 degrees
25+
rounded_deg = round(deg / 10) * 10 % 360
26+
27+
# using cached markers to speed things up
1328
if neighbors <= 1:
14-
return {"color": "red", "size": 20, "marker": "o"}
29+
return {"color": "red", "size": 20, "marker": MARKER_CACHE[rounded_deg]}
1530
elif neighbors >= 2:
16-
return {"color": "green", "size": 20, "marker": (3, 0, 60)}
31+
return {"color": "green", "size": 20, "marker": MARKER_CACHE[rounded_deg]}
1732

1833

1934
model_params = {

mesa/examples/basic/boid_flockers/model.py

+12
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@ def __init__(
4949
seed: Random seed for reproducibility (default: None)
5050
"""
5151
super().__init__(seed=seed)
52+
self.agent_angles = np.zeros(
53+
population_size
54+
) # holds the angle representing the direction of all agents at a given step
5255

5356
# Set up the space
5457
self.space = ContinuousSpace(
@@ -79,6 +82,14 @@ def __init__(
7982
self.average_heading = None
8083
self.update_average_heading()
8184

85+
# vectorizing the calculation of angles for all agents
86+
def calculate_angles(self):
87+
d1 = np.array([agent.direction[0] for agent in self.agents])
88+
d2 = np.array([agent.direction[1] for agent in self.agents])
89+
self.agent_angles = np.degrees(np.arctan2(d1, d2))
90+
for agent, angle in zip(self.agents, self.agent_angles):
91+
agent.angle = angle
92+
8293
def update_average_heading(self):
8394
"""Calculate the average heading (direction) of all Boids."""
8495
if not self.agents:
@@ -96,3 +107,4 @@ def step(self):
96107
"""
97108
self.agents.shuffle_do("step")
98109
self.update_average_heading()
110+
self.calculate_angles()

0 commit comments

Comments
 (0)