diff --git a/src/lib.rs b/src/lib.rs index 9b86446..2656d07 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -41,8 +41,8 @@ const RADIUS: f64 = 250.; const BACKGROUND: &str = "#ffffff"; const BLACK: &str = "#000000"; const RED: &str = "#ff0000"; -const _GREEN: &str = "#00ff00"; -const _BLUE: &str = "#0000ff"; +const GREEN: &str = "#00ff00"; +const BLUE: &str = "#0000ff"; const SCALAR: usize = 0; const E1: usize = 1; @@ -130,6 +130,15 @@ fn draw_point(context: &CanvasRenderingContext2d, point: &CGA) { context.set_fill_style_str(RED); context.arc(x, y, 2., 0., TWO_PI).unwrap(); context.fill(); + + let (x,y) = get_point(point); + let (x,y) = point_to_screen_space(x,y); + + context.begin_path(); + context.set_fill_style_str(BLUE); + context.arc(x, y, 2., 0., TWO_PI).unwrap(); + context.fill(); + } //TODO Integrate into get geometry @@ -161,6 +170,14 @@ fn get_hyperbolic_point(point: &CGA) -> (f64, f64) { (r*x,r*y) } +fn get_point(point: &CGA) -> (f64, f64) { + let x = point[E1]; + let y = point[E2]; + let n = CGA::e4()+CGA::e5(); + let norm = -(point | &n)[SCALAR]; + (x/norm, y/norm) +} + fn get_geometry(circle: &CGA) -> Geometry { //Naively assume we are given a valid line/circle let n_bar = CGA::e4() - CGA::e5(); @@ -193,7 +210,7 @@ fn get_geometry(circle: &CGA) -> Geometry { fn draw_line(context: &CanvasRenderingContext2d, line: &CGA) { context.begin_path(); - context.set_stroke_style_str(_GREEN); + context.set_stroke_style_str(GREEN); let geometry = get_geometry(line); match geometry { @@ -216,6 +233,52 @@ fn draw_line(context: &CanvasRenderingContext2d, line: &CGA) { context.stroke(); } +fn draw_line_between(context: &CanvasRenderingContext2d, a: &CGA, b: &CGA) { + let line = CGA::e4() ^ a ^ b ^ CGA::e3(); + let geometry = get_geometry(&line); + context.begin_path(); + context.set_stroke_style_str(GREEN); + match geometry { + Geometry::Circle(x,y,r) => { + let (a_x, a_y) = get_point(a); + let (b_x, b_y) = get_point(b); + let mut theta_a = (a_y-y).atan2(a_x-x); + let mut theta_b = (b_y-y).atan2(b_x-x); + if theta_a < 0. { + theta_a += TWO_PI; + } + if theta_b < 0. { + theta_b += TWO_PI; + } + let mut delta = theta_b - theta_a; + if delta < -PI { + delta += TWO_PI; + } else if delta > PI { + delta -= TWO_PI; + } + let (x,y) = point_to_screen_space(x,y); + let r = RADIUS*r; + if delta < 0. { + if theta_a + delta < 0. { + context.arc(x, y, r, 0., theta_a).unwrap(); + context.arc(x, y, r, theta_a + delta + TWO_PI, TWO_PI).unwrap(); + } else { + context.arc(x, y, r, theta_a + delta, theta_a).unwrap(); + } + } else { + if theta_a + delta > TWO_PI { + context.arc(x, y, r, theta_a, TWO_PI).unwrap(); + context.arc(x, y, r, 0., theta_a + delta - TWO_PI).unwrap(); + } else { + context.arc(x, y, r, theta_a, theta_a + delta).unwrap(); + } + } + }, + _ => {}, + } + context.stroke(); +} + fn _get_hyperbolic_translation(vec: &CGA) -> CGA { let vec_sqr = (vec * vec)[SCALAR]; if vec_sqr >= 1. { @@ -332,6 +395,9 @@ impl Game { draw_point(&self.context, &p0); draw_point(&self.context, &p1); draw_point(&self.context, &p2); + draw_line_between(&self.context, &p0, &p1); + draw_line_between(&self.context, &p1, &p2); + draw_line_between(&self.context, &p2, &p0); //Construct and draw line pointing straight ahead, to help orient the player. let com_p = com * gen_hyperbolic_point(&CGA::zero()) * com.Reverse();