Add Răhukăla display to the generated SVG

This commit is contained in:
Gergely Polonkai 2022-03-29 08:18:35 +02:00
parent d4d2bea4b0
commit 2ff96bce45
No known key found for this signature in database
GPG Key ID: 2D2885533B869ED4

View File

@ -1,12 +1,12 @@
from datetime import datetime, time from datetime import datetime, time
from math import ceil, cos, pi, radians, sin from math import ceil, cos, pi, radians, sin
from typing import Union from typing import Optional, Union
from astral import LocationInfo, moon from astral import LocationInfo, moon
from pytz import UTC, timezone from pytz import UTC, timezone
from .config import load_config from .config import load_config
from .times import collect_day_parts from .times import collect_day_parts, get_rahukaalam_times
HOURS_AMPM = ( HOURS_AMPM = (
'Midnight', 'Midnight',
@ -94,7 +94,9 @@ def hex_to_rgb(hex_color: str) -> str:
g = int(hex_color[3:5], 16) g = int(hex_color[3:5], 16)
b = int(hex_color[5:7], 16) b = int(hex_color[5:7], 16)
return f'rgb({r}, {g}, {b})' ret = f'rgb({r}, {g}, {b})'
return ret
def get_utc_offset(utc_time: datetime, local_time: datetime): def get_utc_offset(utc_time: datetime, local_time: datetime):
@ -160,12 +162,10 @@ def hour_marker(
hour_name_y = image_width / 2 - outer_r + ring_width / 2 + hour_name_font_size / 4 hour_name_y = image_width / 2 - outer_r + ring_width / 2 + hour_name_font_size / 4
utc_hour_y = image_width / 2 - outer_r + ring_width + utc_font_size utc_hour_y = image_width / 2 - outer_r + ring_width + utc_font_size
ret = f'''<g class="hour {season}" transform="rotate(-172.5, {image_width / 2}, {image_width / 2}) rotate({rotation}, {image_width / 2}, {image_width / 2})"> ret = f'''<g class="hour {season}" transform="rotate({rotation - 172.5}, {image_width / 2}, {image_width / 2})">
<path <path
d="M {x1} {y1} a {outer_r} {outer_r} 15 0 1 {2 * delta_x} 0 l {s_delta_x} {s_delta_y} a {outer_r - ring_width} {outer_r - ring_width} 15 0 0 {i_delta_x} 0 z"></path> d="M {x1} {y1} a {outer_r} {outer_r} 15 0 1 {2 * delta_x} 0 l {s_delta_x} {s_delta_y} a {outer_r - ring_width} {outer_r - ring_width} 15 0 0 {i_delta_x} 0 z"></path>
<text <text
x="{image_width / 2}"
y="{hour_name_y}"
text-anchor="middle" text-anchor="middle"
dominant-baseline="mathematical" dominant-baseline="mathematical"
font-size="{hour_name_font_size}"><textPath xlink:href="#hour-name-path" startOffset="50%">{hour_name}</textPath></text> font-size="{hour_name_font_size}"><textPath xlink:href="#hour-name-path" startOffset="50%">{hour_name}</textPath></text>
@ -194,7 +194,7 @@ def local_hour(
return indent_lines( return indent_lines(
f'''<text f'''<text
transform="rotate(180, {image_width / 2}, {image_width / 2}) rotate({rotation}, {image_width / 2}, {image_width / 2})" transform="rotate({180 + rotation}, {image_width / 2}, {image_width / 2})"
class="local-hour" class="local-hour"
x="{image_width / 2}" x="{image_width / 2}"
y="{image_width / 2 - outer_r - font_size / 2}" y="{image_width / 2 - outer_r - font_size / 2}"
@ -260,6 +260,55 @@ C {h2_x} {bottom_y}, {h2_x} {top_y}, {image_width / 2} {image_width / 2 - radius
return indent_lines(ret, indent) return indent_lines(ret, indent)
def draw_rahukaala(
image_width: float,
rahukaala_radius: float,
rahukaala_width: float,
sun_radius: float,
start: datetime,
end: datetime,
indent: int = 8,
) -> str:
start_deg = time_to_degrees(start)
end_deg = time_to_degrees(end)
alpha = radians(end_deg - start_deg)
delta_x = -rahukaala_radius * sin(alpha)
delta_y = -rahukaala_radius * (1 - cos(alpha))
inner_delta_x = -(rahukaala_radius - rahukaala_width) * sin(alpha)
inner_delta_y = -(rahukaala_radius - rahukaala_width) * (1 - cos(alpha))
s_delta_x = rahukaala_width * sin(alpha)
s_delta_y = -rahukaala_width * cos(alpha)
i_delta_x = -2 * (rahukaala_radius - rahukaala_width) * sin(alpha)
x1 = image_width / 2
y1 = image_width / 2 + rahukaala_radius
x2 = x1 + delta_x
y2 = y1 + delta_y
x4 = x1
y4 = y1 - rahukaala_width
x3 = x4 + inner_delta_x
y3 = y4 + inner_delta_y
ret = f'''<path
transform="rotate({start_deg}, {image_width / 2}, {image_width / 2})"
class="rahukaala"
d="M {x1} {y1}
A {rahukaala_radius} {rahukaala_radius} {end_deg - start_deg} 0 1 {x2} {y2}
A {sun_radius} {sun_radius} 180 1 1 {x3} {y3}
A {rahukaala_radius - rahukaala_width} {rahukaala_radius - rahukaala_width} {end_deg - start_deg} 0 0 {x4} {y4}
A {sun_radius} {sun_radius} 180 1 1 {x1} {y1}
z"></path>'''
return indent_lines(ret, indent)
def get_svg_data( def get_svg_data(
local_time: datetime, local_time: datetime,
image_width: int = 700, image_width: int = 700,
@ -276,6 +325,8 @@ def get_svg_data(
golden_color: str = '#aa842c', golden_color: str = '#aa842c',
day_color: str = '#7dc5f0', day_color: str = '#7dc5f0',
moon_color: str = '#aaaaaa', moon_color: str = '#aaaaaa',
rahukaala_color: str = '#ff7777',
rahukaala_alpha: Optional[int] = None,
local_hour_font_size: float = 16.5, local_hour_font_size: float = 16.5,
hour_name_font_size: float = 13.37699, hour_name_font_size: float = 13.37699,
utc_hour_font_size: float = 15.0234, utc_hour_font_size: float = 15.0234,
@ -293,6 +344,7 @@ def get_svg_data(
golden_rgb = hex_to_rgb(golden_color) golden_rgb = hex_to_rgb(golden_color)
day_rgb = hex_to_rgb(day_color) day_rgb = hex_to_rgb(day_color)
moon_rgb = hex_to_rgb(moon_color) moon_rgb = hex_to_rgb(moon_color)
rahukaala_rgb = hex_to_rgb(rahukaala_color)
hours = HOURS_24 if hour_24 else HOURS_AMPM hours = HOURS_24 if hour_24 else HOURS_AMPM
outer_r = image_width / 2 - 3 * hour_name_font_size outer_r = image_width / 2 - 3 * hour_name_font_size
ring_width = hour_name_font_size * 3 ring_width = hour_name_font_size * 3
@ -325,6 +377,12 @@ def get_svg_data(
noon = day_parts_dict.pop('noon') noon = day_parts_dict.pop('noon')
midnight = day_parts_dict.pop('midnight') midnight = day_parts_dict.pop('midnight')
if rahukaala_alpha is not None:
value = rahukaala_alpha / value
rahukaala_opacity = f' fill-opacity: {value:.2f};'
else:
rahukaala_opacity = ''
ret = f'''<svg width="{image_width}" height="{image_width}" xmlns:xlink="http://www.w3.org/1999/xlink"> ret = f'''<svg width="{image_width}" height="{image_width}" xmlns:xlink="http://www.w3.org/1999/xlink">
<style> <style>
.hour path {{stroke: {hname_stroke_rgb}; stroke-width: {line_width};}} .hour path {{stroke: {hname_stroke_rgb}; stroke-width: {line_width};}}
@ -344,6 +402,7 @@ def get_svg_data(
.moon {{stroke: none; fill: {moon_rgb};}} .moon {{stroke: none; fill: {moon_rgb};}}
.sun {{stroke: none; fill: {line_rgb};}} .sun {{stroke: none; fill: {line_rgb};}}
.dial {{stroke-width: 2px; stroke: {line_rgb};}} .dial {{stroke-width: 2px; stroke: {line_rgb};}}
.rahukaala {{stroke: none; fill: {rahukaala_rgb};{rahukaala_opacity}}}
</style> </style>
<defs> <defs>
{hour_name_path(image_width, outer_r, ring_width)} {hour_name_path(image_width, outer_r, ring_width)}
@ -397,6 +456,12 @@ def get_svg_data(
evening_blue_end.time(), evening_blue_end.time(),
) )
rahukaala_radius = outer_r / 2 + 2 * sun_radius
rahukaala_width = 2 * sun_radius
for start, end in get_rahukaalam_times(location.observer, local_time):
ret += draw_rahukaala(image_width, rahukaala_radius, rahukaala_width, sun_radius, start, end)
ret += f''' <circle cx="{image_width / 2}" cy="{image_width / 2}" r="{marker_radius}" class="marker"></circle> ret += f''' <circle cx="{image_width / 2}" cy="{image_width / 2}" r="{marker_radius}" class="marker"></circle>
</g> </g>
<g>\n''' <g>\n'''