diff --git a/lib/xmet/map.py b/lib/xmet/map.py new file mode 100644 index 0000000..f848639 --- /dev/null +++ b/lib/xmet/map.py @@ -0,0 +1,65 @@ +import cairo +import shapely +import gi + +gi.require_version('Rsvg', '2.0') + +from gi.repository import Rsvg + +MAP_BOUNDS = ( + 49.8, # North + -66.5, # East + 24.2, # South + -125.5 # West +) + +MAP_DIMENSIONS = (MAP_BOUNDS[0] - MAP_BOUNDS[2], + MAP_BOUNDS[1] - MAP_BOUNDS[3]) + +MAP_SCREEN_DIMENSIONS = (1859.0, 968.0) + +class EquirectMap(): + def __init__(self, + width: float, + height: float, + bounds: tuple[float, float, float, float]): + self.width = width + self.height = height + self.bounds = bounds + self.map_width = bounds[1] - bounds[3] + self.map_height = bounds[0] - bounds[2] + + def draw_from_file(self, cr: cairo.Context, path: str): + svg = Rsvg.Handle.new_from_file(path) + + rect = Rsvg.Rectangle() + rect.x = 0 + rect.y = 0 + rect.width = self.width + rect.height = self.height + + svg.render_layer(cr, None, rect) + + def screen_to_map(self, x: float, y: float) -> shapely.Point: + lon = self.bounds[3] + (x / self.width) * self.width + lat = self.bounds[0] + (y / self.height) * self.height + + return shapely.Point(lon, lat) + + def map_to_screen(self, point: shapely.Point) -> tuple[float, float]: + x = ((point.x - self.bounds[3]) / self.map_width) * self.width + y = self.height - ((point.y - self.bounds[2]) / self.map_height) * self.height + + return x, y + + def draw_polygon(self, cr: cairo.Context, poly: shapely.Polygon): + first = True + + for point in poly.exterior.coords: + x, y = self.map_to_screen(shapely.Point(*point)) + + if first: + cr.move_to(x, y) + first = False + else: + cr.line_to(x, y)