diff --git a/src/main.rs b/src/main.rs index 4c66ecf..131f008 100644 --- a/src/main.rs +++ b/src/main.rs @@ -25,6 +25,7 @@ const HOUR_NAMES: [&str; 24] = [ "Blossom", "Ladybug", "Geese", "Dust", "Peach", "Fog", "Acorn", "Gourd", "Soup", "Crow", "Mushroom", "Thunder", "Frost", "Lantern", ]; +const IMAGE_WIDTH: u32 = 700; enum Season { Spring, @@ -69,12 +70,12 @@ fn time_to_degrees(timestamp: i32, // should be time/timestamp seconds_to_degrees(timestamp) } -fn hour_name_path(image_width: u32, outer_r: f32, ring_width: f32) -> Path { +fn hour_name_path(outer_r: f32, ring_width: f32) -> Path { let radius = outer_r - ring_width / 2.0; let delta_x = radius * (15.0_f32.to_radians() / 2.0).sin(); let delta_y = radius * (1.0 - (15.0_f32.to_radians() / 2.0).cos()); - let x1 = (image_width as f32) / 2.0 - delta_x; - let y1 = ((image_width as f32) / 2.0 - radius) + delta_y; + let x1 = (IMAGE_WIDTH as f32) / 2.0 - delta_x; + let y1 = ((IMAGE_WIDTH as f32) / 2.0 - radius) + delta_y; let path_data = PathData::new().move_to((x1, y1)).elliptical_arc_by(( radius, @@ -92,7 +93,6 @@ fn hour_name_path(image_width: u32, outer_r: f32, ring_width: f32) -> Path { fn hour_marker( hour: i32, is_current_hour: bool, - image_width: u32, outer_r: f32, ring_width: f32, hour_name_font_size: f32, @@ -115,10 +115,10 @@ fn hour_marker( let i_delta_x = -2.0 * (outer_r - ring_width) * (15f32.to_radians() / 2.0).sin(); - let x1 = image_width as f32 / 2.0 - delta_x; - let y1 = (image_width as f32 / 2.0 - outer_r) + delta_y; + let x1 = IMAGE_WIDTH as f32 / 2.0 - delta_x; + let y1 = (IMAGE_WIDTH as f32 / 2.0 - outer_r) + delta_y; - let utc_hour_y = image_width as f32 / 2.0 - outer_r + ring_width + utc_hour_font_size; + let utc_hour_y = IMAGE_WIDTH as f32 / 2.0 - outer_r + ring_width + utc_hour_font_size; let path_data = PathData::new() .move_to((x1, y1)) @@ -149,9 +149,9 @@ fn hour_marker( .set("class", "utc") .set( "transform", - format!("rotate(-7.5, {}, {})", image_width / 2, image_width / 2), + format!("rotate(-7.5, {}, {})", IMAGE_WIDTH / 2, IMAGE_WIDTH / 2), ) - .set("x", image_width / 2) + .set("x", IMAGE_WIDTH / 2) .set("y", utc_hour_y) .set("text-anchor", "middle") .set("dominant-baseline", "mathematical") @@ -171,8 +171,8 @@ fn hour_marker( format!( "rotate({}, {}, {})", rotation as f32 - 172.5, - image_width / 2, - image_width / 2 + IMAGE_WIDTH / 2, + IMAGE_WIDTH / 2 ), ) .add(path) @@ -180,13 +180,7 @@ fn hour_marker( .add(utc_hour_text) } -fn get_range_path( - image_width: u32, - radius: f32, - range_name: &str, - start_time: i32, - end_time: i32, -) -> Path { +fn get_range_path(radius: f32, range_name: &str, start_time: i32, end_time: i32) -> Path { let start_deg = time_to_degrees(start_time); let end_deg = time_to_degrees(end_time); let deg_diff = end_deg - start_deg; @@ -197,10 +191,10 @@ fn get_range_path( let end_delta_y = radius * (1.0 - end_deg.to_radians().cos()); let path_data = PathData::new() - .move_to((image_width / 2, image_width / 2)) + .move_to((IMAGE_WIDTH / 2, IMAGE_WIDTH / 2)) .line_to(( - image_width as f32 / 2.0 - start_delta_x, - image_width as f32 / 2.0 + radius - start_delta_y, + IMAGE_WIDTH as f32 / 2.0 - start_delta_x, + IMAGE_WIDTH as f32 / 2.0 + radius - start_delta_y, )) .elliptical_arc_to(( radius, @@ -208,21 +202,21 @@ fn get_range_path( deg_diff, ((start_deg < end_deg) ^ (deg_diff.abs() >= 180.0)) as u8, 0, - image_width as f32 / 2.0 - end_delta_x, - image_width as f32 / 2.0 + radius - end_delta_y, + IMAGE_WIDTH as f32 / 2.0 - end_delta_x, + IMAGE_WIDTH as f32 / 2.0 + radius - end_delta_y, )) .close(); Path::new().set("class", range_name).set("d", path_data) } -fn get_moon_path(image_width: u32, radius: f32, moon_phase: f64) -> Path { +fn get_moon_path(radius: f32, moon_phase: f64) -> Path { let handle_x_pos = radius as f64 * 1.34; let handle_y_pos = radius * 0.88; - let min_x = image_width as f64 / 2.0 - handle_x_pos; + let min_x = IMAGE_WIDTH as f64 / 2.0 - handle_x_pos; let max_x = min_x + 2.0 * handle_x_pos; - let top_y = image_width as f32 / 2.0 - handle_y_pos; - let bottom_y = image_width as f32 / 2.0 + handle_y_pos; + let top_y = IMAGE_WIDTH as f32 / 2.0 - handle_y_pos; + let bottom_y = IMAGE_WIDTH as f32 / 2.0 + handle_y_pos; let h1_x: f64; let h2_x: f64; @@ -236,22 +230,22 @@ fn get_moon_path(image_width: u32, radius: f32, moon_phase: f64) -> Path { } let path_data = PathData::new() - .move_to((image_width as f32 / 2.0, image_width as f32 / 2.0 - radius)) + .move_to((IMAGE_WIDTH as f32 / 2.0, IMAGE_WIDTH as f32 / 2.0 - radius)) .cubic_curve_to(( h1_x, top_y, h1_x, bottom_y, - image_width as f32 / 2.0, - image_width as f32 / 2.0 + radius, + IMAGE_WIDTH as f32 / 2.0, + IMAGE_WIDTH as f32 / 2.0 + radius, )) .cubic_curve_to(( h2_x, bottom_y, h2_x, top_y, - image_width / 2, - image_width as f32 / 2.0 - radius, + IMAGE_WIDTH / 2, + IMAGE_WIDTH as f32 / 2.0 - radius, )); Path::new().set("class", "moon").set("d", path_data) } @@ -267,21 +261,18 @@ fn gen_svg(config: &Option) -> Document { let local_time = local_timestamp.time().num_seconds_from_midnight() as i32; let utc_rotation = seconds_to_degrees(utc_offset); - // TODO: These should be calculated instead of hardcoded - let image_width = 700u32; - // Calculate the Moon phase let unixtime = suncalc::Timestamp(local_timestamp.timestamp_millis()); let moon_illumination = suncalc::moon_illumination(unixtime); - let moon_radius = image_width as f32 * 0.071428571; + let moon_radius = IMAGE_WIDTH as f32 * 0.071428571; let moon_phase = moon_illumination.phase * 28.0; - let local_hour_font_size = image_width as f32 * 0.02357; - let hour_name_font_size = image_width as f32 * 0.019109; - let utc_hour_font_size = image_width as f32 * 0.021462; - let outer_r = (image_width as f32) / 2.0 - 3.0 * hour_name_font_size; + let local_hour_font_size = IMAGE_WIDTH as f32 * 0.02357; + let hour_name_font_size = IMAGE_WIDTH as f32 * 0.019109; + let utc_hour_font_size = IMAGE_WIDTH as f32 * 0.021462; + let outer_r = (IMAGE_WIDTH as f32) / 2.0 - 3.0 * hour_name_font_size; let ring_width = hour_name_font_size * 3.0; - let sun_radius = image_width as f32 * 0.0142871; + let sun_radius = IMAGE_WIDTH as f32 * 0.0142871; let marker_radius = outer_r - ring_width - 2.0 * utc_hour_font_size; let border = Rectangle::new() @@ -319,7 +310,7 @@ fn gen_svg(config: &Option) -> Document { #current-hour-name {font-weight: bold;}", ); - let definitions = Definitions::new().add(hour_name_path(image_width, outer_r, ring_width)); + let definitions = Definitions::new().add(hour_name_path(outer_r, ring_width)); let mut local_clock = Group::new().set("id", "local-clock"); for hour in 0i32..24 { @@ -333,10 +324,10 @@ fn gen_svg(config: &Option) -> Document { let hour_node = Text::new() .set("class", "local-hour") .set("transform", format!("rotate({}, 350, 350)", 180 + rotation)) - .set("x", (image_width as f32) / 2.0) + .set("x", (IMAGE_WIDTH as f32) / 2.0) .set( "y", - (image_width as f32) / 2.0 - outer_r - local_hour_font_size / 2.0, + (IMAGE_WIDTH as f32) / 2.0 - outer_r - local_hour_font_size / 2.0, ) .set("text-anchor", "middle") .set("font-size", local_hour_font_size as f32) @@ -349,8 +340,8 @@ fn gen_svg(config: &Option) -> Document { format!( "rotate({}, {}, {})", utc_rotation, - image_width / 2, - image_width / 2 + IMAGE_WIDTH / 2, + IMAGE_WIDTH / 2 ), ); @@ -358,7 +349,6 @@ fn gen_svg(config: &Option) -> Document { seasonal_clock = seasonal_clock.add(hour_marker( hour, hour == utc_hour as i32, - image_width, outer_r, ring_width, hour_name_font_size, @@ -368,8 +358,8 @@ fn gen_svg(config: &Option) -> Document { let daytime_circle = Circle::new() .set("class", "day-time") - .set("cx", image_width / 2) - .set("cy", image_width / 2) + .set("cx", IMAGE_WIDTH / 2) + .set("cy", IMAGE_WIDTH / 2) .set("r", marker_radius); let day_parts_group: Option = if config.is_some() { @@ -413,7 +403,6 @@ fn gen_svg(config: &Option) -> Document { .num_seconds_from_midnight() as i32; let golden_hour_path = get_range_path( - image_width, marker_radius, "golden-hour", morning_golden_end, @@ -422,33 +411,32 @@ fn gen_svg(config: &Option) -> Document { let sun_disc = Circle::new() .set("class", "sun") - .set("cx", image_width / 2) - .set("cy", image_width as f32 / 2.0 + outer_r / 2.0 + sun_radius) + .set("cx", IMAGE_WIDTH / 2) + .set("cy", IMAGE_WIDTH as f32 / 2.0 + outer_r / 2.0 + sun_radius) .set("r", sun_radius) .set( "transform", format!( "rotate({}, {}, {})", time_to_degrees(local_time) - utc_rotation, - image_width / 2, - image_width / 2 + IMAGE_WIDTH / 2, + IMAGE_WIDTH / 2 ), ); let blue_hour_path = get_range_path( - image_width, marker_radius, "blue-hour", sunrise, // morning_blue_end sunset, // evening_blue_start ); - let nighttime_path = get_range_path(image_width, marker_radius, "night-time", dawn, dusk); + let nighttime_path = get_range_path(marker_radius, "night-time", dawn, dusk); let marker_circle = Circle::new() .set("class", "marker") - .set("cx", image_width / 2) - .set("cy", image_width / 2) + .set("cx", IMAGE_WIDTH / 2) + .set("cy", IMAGE_WIDTH / 2) .set("r", marker_radius); let noon_marker = Line::new() @@ -458,17 +446,17 @@ fn gen_svg(config: &Option) -> Document { format!( "rotate({}, {}, {})", time_to_degrees(noon), - image_width / 2, - image_width / 2 + IMAGE_WIDTH / 2, + IMAGE_WIDTH / 2 ), ) - .set("x1", image_width / 2) + .set("x1", IMAGE_WIDTH / 2) .set( "y1", - image_width as f32 / 2.0 + marker_radius - sun_radius as f32, + IMAGE_WIDTH as f32 / 2.0 + marker_radius - sun_radius as f32, ) - .set("x2", image_width / 2) - .set("y2", image_width as f32 / 2.0 + marker_radius); + .set("x2", IMAGE_WIDTH / 2) + .set("y2", IMAGE_WIDTH as f32 / 2.0 + marker_radius); let midnight_marker = Line::new() .set("class", "mid-marker") @@ -477,17 +465,17 @@ fn gen_svg(config: &Option) -> Document { format!( "rotate({}, {}, {})", time_to_degrees(midnight), - image_width / 2, - image_width / 2 + IMAGE_WIDTH / 2, + IMAGE_WIDTH / 2 ), ) - .set("x1", image_width / 2) + .set("x1", IMAGE_WIDTH / 2) .set( "y1", - image_width as f32 / 2.0 + marker_radius - sun_radius as f32, + IMAGE_WIDTH as f32 / 2.0 + marker_radius - sun_radius as f32, ) - .set("x2", image_width / 2) - .set("y2", image_width as f32 / 2.0 + marker_radius); + .set("x2", IMAGE_WIDTH / 2) + .set("y2", IMAGE_WIDTH as f32 / 2.0 + marker_radius); Some( Group::new() @@ -497,8 +485,8 @@ fn gen_svg(config: &Option) -> Document { format!( "rotate({}, {}, {})", utc_rotation, - image_width / 2, - image_width / 2 + IMAGE_WIDTH / 2, + IMAGE_WIDTH / 2 ), ) .add(daytime_circle) @@ -516,14 +504,14 @@ fn gen_svg(config: &Option) -> Document { let moon_circle = Circle::new() .set("class", "moon-background") - .set("cx", image_width / 2) - .set("cy", image_width / 2) + .set("cx", IMAGE_WIDTH / 2) + .set("cy", IMAGE_WIDTH / 2) .set("r", moon_radius); let moon_group = Group::new() .set("id", "moon-container") .add(moon_circle) - .add(get_moon_path(image_width, moon_radius, moon_phase)); + .add(get_moon_path(moon_radius, moon_phase)); let dial = Line::new() .set("id", "dial") @@ -533,22 +521,22 @@ fn gen_svg(config: &Option) -> Document { format!( "rotate({}, {}, {})", time_to_degrees(local_time), - image_width / 2, - image_width / 2 + IMAGE_WIDTH / 2, + IMAGE_WIDTH / 2 ), ) - .set("x1", image_width / 2) - .set("y1", image_width as f32 / 2.0 + outer_r * 0.5) - .set("x2", image_width / 2) + .set("x1", IMAGE_WIDTH / 2) + .set("y1", IMAGE_WIDTH as f32 / 2.0 + outer_r * 0.5) + .set("x2", IMAGE_WIDTH / 2) .set( "y2", - image_width as f32 / 2.0 + outer_r - ring_width + hour_name_font_size, + IMAGE_WIDTH as f32 / 2.0 + outer_r - ring_width + hour_name_font_size, ); - let current_box_width = (200f32 / 700f32) * image_width as f32; - let current_box_height = (100f32 / 700f32) * image_width as f32; - let current_hour_name_font_size = (40f32 / 700f32) * image_width as f32; - let current_time_font_size = (30f32 / 700f32) * image_width as f32; + let current_box_width = (200f32 / 700f32) * IMAGE_WIDTH as f32; + let current_box_height = (100f32 / 700f32) * IMAGE_WIDTH as f32; + let current_hour_name_font_size = (40f32 / 700f32) * IMAGE_WIDTH as f32; + let current_time_font_size = (30f32 / 700f32) * IMAGE_WIDTH as f32; let current_hour_rect = Rectangle::new() .set("x1", 0) @@ -591,8 +579,8 @@ fn gen_svg(config: &Option) -> Document { "transform", format!( "translate({}, {})", - image_width as f32 / 2.0 - current_box_width / 2.0, - image_width as f32 / 2.0 + top_pos + IMAGE_WIDTH as f32 / 2.0 - current_box_width / 2.0, + IMAGE_WIDTH as f32 / 2.0 + top_pos ), ) .add(current_hour_rect)