| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160 |
- from geoplotlib.layers import BaseLayer
- from geoplotlib.core import BatchPainter
- import geoplotlib
- from geoplotlib.utils import BoundingBox, epoch_to_str
- import pyglet
- import pandas as pd
- import numpy as np
- from de2.routing import get_graph, euler_distance, pathfinder, find_percentage_point_in_path as fpp
- class PoABLayer(BaseLayer):
- """
- Renders the map.
- """
- __colors__ = {
- "highlight": [255, 255, 0, 100],
- "nodes": [150, 0, 250, 200],
- "sailing": [0, 150, 250, 200],
- "tugging": [150, 250, 0, 200]
- }
- def __init__(self, sim=None):
- self.sim = sim
- self.sim_active = False
- self.berths = pd.read_csv("berths.csv")
- self.berths["used"] = False
- self.paths = pd.read_csv("2022.csv")
- self.paths.drop_duplicates(["Locatie van", "Locatie naar"], inplace=True)
- for _, traj in self.paths.iterrows():
- self.berths.loc[self.berths["lpl_id"] == traj["Locatie van"], "used"] = True
- self.berths.loc[self.berths["lpl_id"] == traj["Locatie naar"], "used"] = True
- self.berths = self.berths[self.berths["used"]]
- self.paths = []
- self.painter = BatchPainter()
- self.vcache = {} # vessel -> source
- self.pcache = {} # vessel -> path, dists
- self.graph = get_graph()
- def draw_shape(self, x, y):
- """
- Draws the shape on the layer, at a specific location.
- Args:
- x (numeric): The x-position to draw this shape at.
- y (numeric): The y-position to draw this shape at.
- """
- self.painter.points(x, y, 5)
- def draw_path(self, path, proj):
- """
- Draws a path on the layer.
- Args:
- path: The path to draw as (x, y) tuples.
- proj: The projector.
- """
- for ix in range(len(path) - 1):
- point1 = path[ix]
- point2 = path[ix + 1]
- vx1, vy1 = proj.lonlat_to_screen(np.asarray([point1[0]]), np.asarray([point1[1]]))
- vx2, vy2 = proj.lonlat_to_screen(np.asarray([point2[0]]), np.asarray([point2[1]]))
- self.painter.lines(vx1, vy1, vx2, vy2, width=1.5)
- def draw(self, proj, mouse_x, mouse_y, ui_manager):
- self.painter = BatchPainter()
- tooltips = []
- self.painter.set_color(self.__colors__["nodes"])
- if not self.sim_active:
- ui_manager.status("Press Space to Start Simulation")
- else:
- model = self.sim.model
- time = model.clock.state["time"]
- ts = int(time + model.tracer.starting_time / 1000)
- ui_manager.info("TIME: %s" % epoch_to_str(ts))
- for vessel in model.sailer.state["vessels"]:
- if vessel.source is not None or vessel.target is not None:
- if vessel.task == "sailing":
- self.painter.set_color(self.__colors__["sailing"])
- else:
- self.painter.set_color(self.__colors__["tugging"])
- if vessel.mmsi not in self.vcache or self.vcache[vessel.mmsi] != vessel.source:
- self.vcache[vessel.mmsi] = vessel.source
- self.pcache[vessel.mmsi] = pathfinder(self.graph, vessel.source, vessel.target)
- path, dists = self.pcache[vessel.mmsi]
- self.draw_path(path, proj)
- tot_distance = vessel.total_distance
- traveled_approx = tot_distance - vessel.distance_left
- delta = time - model.sailer.state["time"]
- traveled_approx += delta * vessel.velocity
- percentage = traveled_approx / tot_distance
- if sum(dists) == 0:
- p1 = p2 = path[0]
- percentage = 1.
- else:
- p1, p2, percentage = fpp(path, dists, percentage)
- sx, sy = proj.lonlat_to_screen(np.asarray([p1[0]]), np.asarray([p1[1]]))
- tx, ty = proj.lonlat_to_screen(np.asarray([p2[0]]), np.asarray([p2[1]]))
- dx = (tx - sx) * percentage
- dy = (ty - sy) * percentage
- if euler_distance(sx + dx, sy + dy, mouse_x, mouse_y) < 10:
- self.painter.set_color(self.__colors__["highlight"])
- tooltips.append("%s (MMSI: %s)" % (str(vessel.name), str(vessel.mmsi)))
- tooltips.append("%.3f m/s" % vessel.velocity)
- self.draw_shape(sx + dx, sy + dy)
- ui_manager.tooltip("\n".join(tooltips))
- self.painter.batch_draw()
- def bbox(self):
- box = [max(self.berths["center_lat"]), max(self.berths["center_lon"]), min(self.berths["center_lat"]), min(self.berths["center_lon"])]
- return BoundingBox(north=box[0], east=box[1], south=box[2], west=box[3])
- def on_key_release(self, key, modifiers):
- if key == pyglet.window.key.SPACE:
- if self.sim is not None:
- self.sim.simulate()
- self.sim_active = True
- if __name__ == '__main__':
- from de2.elements import Port
- from pypdevs.simulator import Simulator
- port = Port("PoAB", "results-de/IVEF.csv")
- sim = Simulator(port)
- sim.setClassicDEVS()
- sim.setRealTime(scale=0.0002)
- sim.setTerminationTime(14 * 24 * 60 * 60) # 14 days
- layer = PoABLayer(sim)
- geoplotlib.set_window_size(640, 760)
- geoplotlib.tiles_provider({
- 'url': lambda zoom, xtile, ytile: 'https://tile.openstreetmap.org/%d/%d/%d.png' % (zoom, xtile, ytile),
- 'tiles_dir': 'mytiles',
- 'attribution': 'Map tiles by Stamen Design, under CC BY 3.0. Data @ OpenStreetMap contributors.'
- })
- geoplotlib.add_layer(layer)
- geoplotlib.show()
- sim.model.print_statistics()
|