diff --git a/src/lib.rs b/src/lib.rs index 293fd51..aeb33d5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -63,6 +63,11 @@ struct Ship { _orientation: CGA, } +enum Geometry { + Circle(f64, f64, f64), //x,y,r + Line(f64, f64, f64) //x,r,theta +} + fn point_to_cga(x: f64, y: f64) -> CGA { let x_vec = CGA::e1(); let y_vec = CGA::e2(); @@ -100,54 +105,56 @@ fn draw_point(context: &CanvasRenderingContext2d, point: &CGA) { context.fill(); } +fn get_geometry(circle: &CGA) -> Geometry { + //Naively assume we are given a valid line/circle + let n_bar = CGA::e4() - CGA::e5(); + let n_vec = CGA::e4() + CGA::e5(); + let dual = circle.Dual(); + let l = (&dual | &n_vec)[SCALAR]; + let c = (&dual | &n_bar)[SCALAR]; + let a = (&dual | CGA::e1())[SCALAR]; + let b = (&dual | CGA::e2())[SCALAR]; + + if l.abs() < ERROR { + //LINE + let theta = (-a).atan2(b); + let norm_sqr = a*a + b*b; + if norm_sqr < ERROR { + panic!("Not a line or circle"); + } + let x = a*c/norm_sqr/2.; + let y = b*c/norm_sqr/2.; + return Geometry::Line(x,y,theta); + } else { + //Circle + let c_x = a/l; + let c_y = b/l; + let r_sqr = c_x*c_x + c_y*c_y + c/l; + let r = r_sqr.sqrt(); + return Geometry::Circle(-c_x, -c_y, r); + } +} + fn draw_line(context: &CanvasRenderingContext2d, line: &CGA) { context.begin_path(); context.set_stroke_style_str(GREEN); - //Naively assume we are given a valid line/circle - let n_bar = CGA::e4() - CGA::e5(); - let n_vec = CGA::e4() + CGA::e5(); - let dual = line.Dual(); - - let lambda = -(&dual | &n_vec)[SCALAR]; - let mu = (&dual | &n_bar)[SCALAR]; - let x = dual[E1]; - let y = dual[E2]; - - - if lambda.abs() < ERROR { - //Line - let norm_sqr = x*x+y*y; - if norm_sqr < ERROR { - return; - } else { - let norm = norm_sqr.sqrt(); - let px = mu * 0.5 * x / norm_sqr; - let py = mu * 0.5 * y / norm_sqr; - let tx = -y / norm; - let ty = x / norm; - let p1x = px + tx * 1000.; - let p1y = py + ty * 1000.; - let p2x = px - tx * 1000.; - let p2y = py - ty * 1000.; + let geometry = get_geometry(line); + match geometry { + Geometry::Circle(x,y,r) => { + let (canvas_x, canvas_y) = point_to_screen_space(x, y); + let canvas_r = r*RADIUS; + context.arc(canvas_x, canvas_y, canvas_r, 0., TWO_PI).unwrap(); + }, + Geometry::Line(x,y,theta) => { + let (p1x, p1y) = (x - theta.cos(), y - theta.sin()); + let (p2x, p2y) = (x + theta.cos(), y + theta.sin()); let (canvas_x1, canvas_y1) = point_to_screen_space(p1x, p1y); let (canvas_x2, canvas_y2) = point_to_screen_space(p2x, p2y); + draw_point(&context, &point_to_cga(x,y)); context.move_to(canvas_x1, canvas_y1); context.line_to(canvas_x2, canvas_y2); - - } - } else { - //Extract Center and Radius - let c_x = x/lambda; - let c_y = y/lambda; - let r_sqr = c_x*c_x + c_y*c_y - mu/lambda; - let r = r_sqr.sqrt(); - - //draw_point(context, &point_to_cga(c_x, c_y)); - - let (canvas_x, canvas_y) = point_to_screen_space(c_x, c_y); - let canvas_r = r*RADIUS; - context.arc(canvas_x, canvas_y, canvas_r, 0., TWO_PI).unwrap(); + }, } context.stroke(); }