Implement SPCOutlookMap class
This commit is contained in:
parent
5484fb3bb8
commit
8755d4d899
1 changed files with 99 additions and 5 deletions
|
@ -2,9 +2,11 @@ import re
|
|||
import enum
|
||||
import shapely
|
||||
import datetime
|
||||
import cairo
|
||||
|
||||
from xmet.db import DatabaseTable
|
||||
from xmet.coord import COORD_SYSTEM
|
||||
from xmet.map import EquirectMap, MAP_SCREEN_DIMENSIONS, MAP_BOUNDS
|
||||
from xmet.afos import MONTHS, TIMEZONES
|
||||
|
||||
from pyiem.nws.products._outlook_util import (
|
||||
|
@ -114,7 +116,7 @@ def each_poly(parts: list[str]):
|
|||
polygons, interiors, linestrings = convert_segments(segments)
|
||||
|
||||
#
|
||||
# we do our winding logic now
|
||||
# We do our winding logic now
|
||||
#
|
||||
polygons.extend(winding_logic(linestrings))
|
||||
|
||||
|
@ -123,7 +125,9 @@ def each_poly(parts: list[str]):
|
|||
#
|
||||
for interior in interiors:
|
||||
for i, polygon in enumerate(polygons):
|
||||
if not polygon.intersection(interior).is_empty:
|
||||
if polygon.intersection(interior).is_empty:
|
||||
continue
|
||||
|
||||
current = list(polygon.interiors)
|
||||
current.append(interior)
|
||||
polygons[i] = shapely.Polygon(polygon.exterior, current)
|
||||
|
@ -165,6 +169,9 @@ class SPCOutlookArea(DatabaseTable):
|
|||
self.outlook_id = None
|
||||
self.poly = None
|
||||
|
||||
def sort_value(self):
|
||||
raise NotImplementedError
|
||||
|
||||
class SPCOutlookProbabilityArea(SPCOutlookArea):
|
||||
__slots__ = (
|
||||
'hazard', 'probability', 'sig',
|
||||
|
@ -177,6 +184,12 @@ class SPCOutlookProbabilityArea(SPCOutlookArea):
|
|||
'id', 'outlook_id', 'hazard', 'probability', 'sig', 'poly'
|
||||
)
|
||||
|
||||
def sort_value(self):
|
||||
if self.probability == 'SIGN':
|
||||
return 1.0
|
||||
|
||||
return float(self.probability)
|
||||
|
||||
class SPCOutlookCategoryArea(SPCOutlookArea):
|
||||
__slots__ = (
|
||||
'category'
|
||||
|
@ -189,6 +202,18 @@ class SPCOutlookCategoryArea(SPCOutlookArea):
|
|||
'id', 'outlook_id', 'category', 'poly'
|
||||
)
|
||||
|
||||
__category_levels__ = {
|
||||
'TSTM': 0,
|
||||
'MRGL': 1,
|
||||
'SLGT': 2,
|
||||
'ENH': 3,
|
||||
'MDT': 4,
|
||||
'HIGH': 5
|
||||
}
|
||||
|
||||
def sort_value(self):
|
||||
return self.__category_levels__[self.category]
|
||||
|
||||
class SPCOutlook():
|
||||
__slots__ = (
|
||||
'id', 'timestamp_issued', 'timestamp_start', 'timestamp_end', 'day',
|
||||
|
@ -216,6 +241,12 @@ class SPCOutlook():
|
|||
self.probabilities = list()
|
||||
self.categories = list()
|
||||
|
||||
def sorted_probabilities(self) -> list[SPCOutlookProbabilityArea]:
|
||||
return sorted(self.probabilities, key=lambda p: p.sort_value())
|
||||
|
||||
def sorted_categories(self) -> list[SPCOutlookCategoryArea]:
|
||||
return sorted(self.categories, key=lambda p: p.sort_value())
|
||||
|
||||
class SPCOutlookParserState(enum.Enum):
|
||||
HEADER = 1
|
||||
OFFICE = enum.auto()
|
||||
|
@ -455,3 +486,66 @@ class SPCOutlookParser():
|
|||
self.parse_body(line)
|
||||
|
||||
return self.outlook
|
||||
|
||||
class SPCOutlookMap(EquirectMap):
|
||||
TEXT_FONT = 'Muli'
|
||||
|
||||
LOGO_RATIO = 75.0 / 275.0
|
||||
LOGO_WIDTH = 360
|
||||
LOGO_HEIGHT = LOGO_RATIO * LOGO_WIDTH
|
||||
LOGO_MARGIN = 16
|
||||
|
||||
__category_colors__ = {
|
||||
'TSTM': (212, 240, 213),
|
||||
'MRGL': ( 80, 201, 134),
|
||||
'SLGT': (255, 255, 81),
|
||||
'ENH': (255, 192, 108),
|
||||
'MDT': (255, 80, 80),
|
||||
'HIGH': (255, 80, 255)
|
||||
}
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(*MAP_SCREEN_DIMENSIONS, MAP_BOUNDS)
|
||||
|
||||
def draw_logo(self, cr: cairo.Context, path: str):
|
||||
width = self.LOGO_WIDTH
|
||||
height = self.LOGO_HEIGHT
|
||||
margin = self.LOGO_MARGIN
|
||||
|
||||
x = margin
|
||||
y = self.height - height - margin
|
||||
|
||||
self.draw_from_file(cr, path, x, y, width, height)
|
||||
|
||||
def draw_annotation(self, cr: cairo.Context, text: str):
|
||||
cr.select_font_face('Muli')
|
||||
cr.set_font_size(28)
|
||||
|
||||
extents = cr.text_extents(text)
|
||||
|
||||
cr.move_to(self.width - extents.width - 48,
|
||||
self.height - extents.height - 16)
|
||||
|
||||
cr.show_text(text)
|
||||
|
||||
def draw_categories(self,
|
||||
cr: cairo.Context,
|
||||
outlook: SPCOutlook):
|
||||
cr.save()
|
||||
|
||||
for category in outlook.sorted_categories():
|
||||
color = self.__category_colors__[category.category]
|
||||
|
||||
r = color[0] / 255.0
|
||||
g = color[1] / 255.0
|
||||
b = color[2] / 255.0
|
||||
|
||||
cr.set_source_rgba(r, g, b, 0.35)
|
||||
self.draw_polygon(cr, category.poly)
|
||||
cr.fill()
|
||||
|
||||
cr.set_source_rgba(r*0.75, g*0.75, b*0.75, 0.8)
|
||||
self.draw_polygon(cr, category.poly)
|
||||
cr.stroke()
|
||||
|
||||
cr.restore()
|
||||
|
|
Loading…
Add table
Reference in a new issue