Skip to content

Commit

Permalink
feat: rework edges and add parallel lines
Browse files Browse the repository at this point in the history
  • Loading branch information
CalliEve committed Sep 5, 2024
1 parent 6b595c1 commit 5443936
Show file tree
Hide file tree
Showing 19 changed files with 1,043 additions and 503 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ version = "0.1.0"
edition = "2021"

[dependencies]
leptos = { version = "0.6.11", features = ["csr", "nightly"] }
leptos = { version = "0.6.14", features = ["csr", "nightly"] }
web-sys = { version = "0.3", features = ["KeyboardEvent", "HtmlCanvasElement", "HtmlInputElement", "FileList", "File", "Blob", "CanvasRenderingContext2d", "CssStyleDeclaration", "Element", "Window"] }
wasm-bindgen = { version = "0.2" }
console_log = "1"
Expand Down
35 changes: 35 additions & 0 deletions src/algorithm/calc_direction.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#[derive(Debug, Clone, Copy)]
pub enum EdgeDirection {
Up,
DiagUpRight,
Right,
DiagDownRight,
Down,
DiagDownLeft,
Left,
DiagUpLeft,
Equal,
}

/// Calculates the direction the edge is moving.
pub fn calc_direction(from_x: f64, from_y: f64, to_x: f64, to_y: f64) -> EdgeDirection {
if from_x == to_x && from_y > to_y {
EdgeDirection::Up
} else if from_x < to_x && from_y > to_y {
EdgeDirection::DiagUpRight
} else if from_x < to_x && from_y == to_y {
EdgeDirection::Right
} else if from_x < to_x && from_y < to_y {
EdgeDirection::DiagDownRight
} else if from_x == to_x && from_y < to_y {
EdgeDirection::Down
} else if from_x > to_x && from_y < to_y {
EdgeDirection::DiagDownLeft
} else if from_x > to_x && from_y == to_y {
EdgeDirection::Left
} else if from_x > to_x && from_y > to_y {
EdgeDirection::DiagUpLeft
} else {
EdgeDirection::Equal
}
}
45 changes: 31 additions & 14 deletions src/algorithm/closest_corner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,12 @@ use crate::{
/// Calculates the coordinate of the corner (on an octilinear grid) of a station
/// closest to the given neigbor. An offset is provided for, if the corner is
/// further from the middle of the station coordinate.
pub fn calc_closest_corner(from: (f64, f64), to: (f64, f64), state: CanvasState) -> (f64, f64) {
pub fn calc_closest_corner(
from: (f64, f64),
to: (f64, f64),
state: CanvasState,
height_offset: f64,
) -> (f64, f64) {
let cardinal_offset = state.drawn_square_size() / PI;
let corner_offset = state.drawn_square_size() / PI * 0.8;

Expand All @@ -17,35 +22,47 @@ pub fn calc_closest_corner(from: (f64, f64), to: (f64, f64), state: CanvasState)

if equal_pixel(from_x, to_x) {
if from_y > to_y {
(from_x, from_y - cardinal_offset) // below
(
from_x + height_offset,
from_y - cardinal_offset,
) // below
} else {
(from_x, from_y + cardinal_offset) // above
(
from_x - height_offset,
from_y + cardinal_offset,
) // above
}
} else if from_x > to_x {
if equal_pixel(from_y, to_y) {
(from_x - cardinal_offset, from_y) // left
(
from_x - cardinal_offset,
from_y - height_offset,
) // left
} else if from_y > to_y {
(
from_x - corner_offset,
from_y - corner_offset,
from_x - corner_offset + height_offset,
from_y - corner_offset - height_offset,
) // below left
} else {
(
from_x - corner_offset,
from_y + corner_offset,
from_x - corner_offset - height_offset,
from_y + corner_offset - height_offset,
) // above left
}
} else if equal_pixel(from_y, to_y) {
(from_x + cardinal_offset, from_y) // right
(
from_x + cardinal_offset,
from_y + height_offset,
) // right
} else if from_y > to_y {
(
from_x + corner_offset,
from_y - corner_offset,
from_x + corner_offset + height_offset,
from_y - corner_offset + height_offset,
) // below right
} else {
(
from_x + corner_offset,
from_y + corner_offset,
from_x + corner_offset - height_offset,
from_y + corner_offset + height_offset,
) // above right
}
}
Expand All @@ -58,7 +75,7 @@ mod tests {
let mut state = CanvasState::new();
state.set_square_size(3);

let result = calc_closest_corner(from, to, state);
let result = calc_closest_corner(from, to, state, 0.0);
let (result_x, result_y) = result;
let (expected_x, expected_y) = expected;

Expand Down
31 changes: 29 additions & 2 deletions src/algorithm/draw_edge.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,38 @@
use web_sys::CanvasRenderingContext2d;

use super::closest_corner::calc_closest_corner;
use super::{
calc_direction::{
calc_direction,
EdgeDirection,
},
closest_corner::calc_closest_corner,
};
use crate::{
components::CanvasState,
models::GridNode,
};

pub fn add_offset(offset: f64, x: f64, y: f64, direction: EdgeDirection) -> (f64, f64) {
match direction {
EdgeDirection::Up => (x + offset, y),
EdgeDirection::DiagUpRight => (x + offset, y + offset),
EdgeDirection::Right => (x, y + offset),
EdgeDirection::DiagDownRight => (x - offset, y + offset),
EdgeDirection::Down => (x - offset, y),
EdgeDirection::DiagDownLeft => (x - offset, y - offset),
EdgeDirection::Left => (x, y - offset),
EdgeDirection::DiagUpLeft => (x + offset, y - offset),
EdgeDirection::Equal => (x, y),
}
}

pub fn draw_edge(
from: GridNode,
to: GridNode,
steps: &[GridNode],
canvas: &CanvasRenderingContext2d,
state: CanvasState,
height_offset: f64,
) {
let from_pos = from.to_canvas_pos(state);
let to_pos = to.to_canvas_pos(state);
Expand All @@ -22,12 +43,17 @@ pub fn draw_edge(
.first()
.map_or(to_pos, |s| s.to_canvas_pos(state)),
state,
height_offset,
);
canvas.move_to(from_x, from_y);

let mut last_is = state.is_on_canvas(from);
let mut last_pos = (from_x, from_y);
for step in steps {
let (step_x, step_y) = step.to_canvas_pos(state);
let (mut step_x, mut step_y) = step.to_canvas_pos(state);
let direction = calc_direction(last_pos.0, last_pos.1, step_x, step_y);
last_pos = (step_x, step_y);
(step_x, step_y) = add_offset(height_offset, step_x, step_y, direction);

let step_is = state.is_on_canvas(*step);
if !last_is && !step_is {
Expand All @@ -45,6 +71,7 @@ pub fn draw_edge(
.last()
.map_or(from_pos, |s| s.to_canvas_pos(state)),
state,
-height_offset,
);
canvas.line_to(to_x, to_y);
}
16 changes: 6 additions & 10 deletions src/algorithm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use web_sys::{
};

mod a_star;
mod calc_direction;
mod closest_corner;
mod draw_edge;
mod grid;
Expand All @@ -15,10 +16,7 @@ pub use a_star::run_a_star;
pub use draw_edge::draw_edge;
use grid::draw_grid;

use crate::{
components::MapState,
models::Drawable,
};
use crate::components::MapState;

/// Redraws the given canvas based on the given state
pub fn redraw_canvas(canvas: &HtmlCanvasElement, state: &MapState) {
Expand All @@ -32,17 +30,15 @@ pub fn redraw_canvas(canvas: &HtmlCanvasElement, state: &MapState) {

draw_grid(&context, state.get_canvas_state());

let draw_drawable = |d: &dyn Drawable| d.draw(&context, state.get_canvas_state());
let map = state.get_map();

state
.get_map()
.inspect(|d| draw_drawable(*d));
map.draw(&context, state.get_canvas_state());

state
.get_selected_station()
.inspect(|d| draw_drawable(*d));
.inspect(|d| d.draw(map, &context, state.get_canvas_state()));

state
.get_selected_line()
.inspect(|d| draw_drawable(*d));
.inspect(|d| d.draw(map, &context, state.get_canvas_state()));
}
46 changes: 21 additions & 25 deletions src/components/molecules/canvas.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,12 +116,9 @@ fn canvas_click_pos(map_size: (u32, u32), ev: &UiEvent) -> (f64, f64) {
///
/// [mousedown]: https://developer.mozilla.org/en-US/docs/Web/API/Element/mousedown_event
fn on_mouse_down(map_state: &mut MapState, ev: &UiEvent) {
let Some(mut map) = map_state
let mut map = map_state
.get_map()
.cloned()
else {
return;
};
.clone();
let canvas_state = map_state.get_canvas_state();

// Handle a click while having a new station selected.
Expand All @@ -143,16 +140,13 @@ fn on_mouse_down(map_state: &mut MapState, ev: &UiEvent) {
.get_selected_line()
.cloned()
{
if let Some(station_at_pos) = map
.station_at_node(mouse_pos)
.cloned()
{
if let Some(station_at_pos) = map.station_at_node(mouse_pos) {
let (before, after) = selected_line.get_before_after();
let mut line = selected_line
.get_line()
let mut line = map
.get_or_add_line(selected_line.get_line())
.clone();

line.add_station(station_at_pos, before, after);
line.add_station(&mut map, station_at_pos, before, after);

map.add_line(line);
map_state.set_map(map);
Expand All @@ -163,13 +157,19 @@ fn on_mouse_down(map_state: &mut MapState, ev: &UiEvent) {

if let Some(mut selected_station) = map
.station_at_node(mouse_pos)
.and_then(|s| map.get_station(s))
.map(Station::clone_non_ref)
.map(SelectedStation::new)
{
for line in map.get_lines() {
let (before, after) = line.get_station_neighbors(selected_station.get_station());
selected_station.add_before(before);
selected_station.add_after(after);
let (before, after) = line.get_station_neighbors(
&map,
selected_station
.get_station()
.get_id(),
);
selected_station.add_before(before);
selected_station.add_after(after);
}

map_state.set_selected_station(selected_station);
Expand All @@ -179,7 +179,7 @@ fn on_mouse_down(map_state: &mut MapState, ev: &UiEvent) {
if let Some(selected_line) = map
.line_at_node(mouse_pos)
.cloned()
.map(|l| SelectedLine::new(l, mouse_pos, Some(mouse_pos)))
.map(|l| SelectedLine::new(l, &map, mouse_pos, Some(mouse_pos)))
{
map_state.set_selected_line(selected_line);
}
Expand All @@ -191,8 +191,7 @@ fn on_mouse_down(map_state: &mut MapState, ev: &UiEvent) {
fn on_mouse_up(map_state: &mut MapState, ev: &UiEvent) {
let mut map = map_state
.get_map()
.cloned()
.unwrap();
.clone();

// Handle a mouseup while having a line selected
if let Some(selected_line) = map_state
Expand All @@ -203,16 +202,13 @@ fn on_mouse_up(map_state: &mut MapState, ev: &UiEvent) {
let canvas_pos = canvas_click_pos(canvas_state.get_size(), ev);
let mouse_pos = GridNode::from_canvas_pos(canvas_pos, canvas_state);

if let Some(station_at_pos) = map
.station_at_node(mouse_pos)
.cloned()
{
if let Some(station_at_pos) = map.station_at_node(mouse_pos) {
let (before, after) = selected_line.get_before_after();
let mut line = selected_line
.get_line()
let mut line = map
.get_or_add_line(selected_line.get_line())
.clone();

line.add_station(station_at_pos, before, after);
line.add_station(&mut map, station_at_pos, before, after);

map.add_line(line);
map_state.set_map(map);
Expand Down
Loading

0 comments on commit 5443936

Please sign in to comment.