-
Notifications
You must be signed in to change notification settings - Fork 883
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Visualization changes #1278
base: main
Are you sure you want to change the base?
Visualization changes #1278
Changes from all commits
fce4a85
1e4e46f
ed6921f
6a939f5
8bc5b50
9f6587d
d66924f
0858679
8a2b3fe
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -28,6 +28,7 @@ def __init__(self, unique_id: int, model: "Model") -> None: | |
self.unique_id = unique_id | ||
self.model = model | ||
self.pos: Optional[Position] = None | ||
self.heading = 90 | ||
|
||
def step(self) -> None: | ||
"""A single step of the agent.""" | ||
|
@@ -36,6 +37,81 @@ def step(self) -> None: | |
def advance(self) -> None: | ||
pass | ||
|
||
def move_forward_or_backward(self, amount, sign): | ||
"""Does the calculation to find the agent's next move and is used within the forward and backward functions""" | ||
new_x = float(self.pos[0]) + sign * math.cos(self.heading * math.pi / 180) * amount | ||
new_y = float(self.pos[1]) + sign * math.sin(self.heading * math.pi / -180) * amount | ||
next_pos = (new_x, new_y) | ||
try: | ||
self.model.space.move_agent(self, next_pos) | ||
except: | ||
print("agent.py (forward_backwards): could not move agent within self.model.space") | ||
|
||
def move_forward(self, amount): | ||
"""Moves the agent forward by the amount given""" | ||
self.move_forward_or_backward(amount, 1) | ||
|
||
def move_backward(self, amount): | ||
"""Moves the agent backwards from where its facing by the given amount""" | ||
self.move_forward_or_backward(amount, -1) | ||
|
||
def turn_right(self, degree): | ||
"""Turns the agent right by the given degree""" | ||
self.heading = (self.heading - degree) % 360 | ||
|
||
def turn_left(self, degree): | ||
"""Turns the agent left by the given degree""" | ||
self.heading = (self.heading + degree) % 360 | ||
|
||
def setxy(self, x, y): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What about There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
"""Sets the current position to the specified x,y parameters""" | ||
self.pos = (x, y) | ||
|
||
def set_pos(self, apos): | ||
"""Sets the current position to the specified pos parameter""" | ||
self.pos = apos | ||
|
||
def distancexy(self, x, y): | ||
"""Gives you the distance of the agent and the given coordinate""" | ||
return math.dist(self.pos, (x, y)) | ||
|
||
def distance(self, another_agent): | ||
"""Gives you the distance between the agent and another agent""" | ||
return self.distancexy(another_agent.pos[0], another_agent.pos[1]) | ||
|
||
def die(self): | ||
"""Removes the agent from the schedule and the grid """ | ||
try: | ||
self.model.schedule.remove(self) | ||
except: | ||
print("agent.py (die): could not remove agent from self.model.schedule") | ||
try: | ||
self.model.space.remove_agent(self) | ||
except: | ||
print("agent.py (die): could not remove agent from self.model.space") | ||
|
||
def towardsxy(self, x, y): | ||
"""Calculates angle between a given coordinate and horizon as if the current position is the origin""" | ||
dx = x - float(self.pos[0]) | ||
dy = float(self.pos[1]) - y | ||
if dx == 0: | ||
return 90 if dy > 0 else 270 | ||
else: | ||
return math.degrees(math.atan2(dy, dx)) | ||
|
||
def towards(self, another_agent): | ||
"""Calculates angle between an agent and horizon as if the current position is the origin""" | ||
return self.towardsxy(*another_agent.pos) | ||
|
||
def facexy(self, x, y): | ||
"""Makes agent face a given coordinate""" | ||
self.heading = self.towardsxy(x, y) | ||
|
||
def face(self, another_agent): | ||
"""Makes agent face another agent""" | ||
x, y = another_agent.pos | ||
self.facexy(x, y) | ||
|
||
@property | ||
def random(self) -> Random: | ||
return self.model.random |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
from mesa.visualization.ModularVisualization import VisualizationElement | ||
|
||
|
||
class SimpleCanvas(VisualizationElement): | ||
local_includes = ["simple_continuous_canvas.js"] | ||
portrayal_method = None | ||
canvas_height = 500 | ||
canvas_width = 500 | ||
|
||
def __init__(self, portrayal_method, canvas_height=500, canvas_width=500, background_src=None): | ||
""" | ||
Instantiate a new SimpleCanvas | ||
""" | ||
self.portrayal_method = portrayal_method | ||
self.canvas_height = canvas_height | ||
self.canvas_width = canvas_width | ||
self.background_src = background_src | ||
new_element = "new Simple_Continuous_Module({}, {}, {})".format( | ||
self.canvas_width, self.canvas_height, "'" + self.background_src + "'" if self.background_src != None else "null" | ||
) | ||
self.js_code = "elements.push(" + new_element + ");" | ||
|
||
def render(self, model): | ||
space_state = [] | ||
for obj in model.schedule.agents: | ||
portrayal = self.portrayal_method(obj) | ||
x, y = obj.pos | ||
x = (x - model.space.x_min) / (model.space.x_max - model.space.x_min) | ||
y = (y - model.space.y_min) / (model.space.y_max - model.space.y_min) | ||
portrayal["x"] = x | ||
portrayal["y"] = y | ||
portrayal["heading"] = obj.heading | ||
space_state.append(portrayal) | ||
return space_state |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should define a new class for the new attribute and methods,
AgentWithHeading
/AgentWithDirection
/ if you have a better name for it. Because not all models need the feature.