Split the geometry finding code from the drawing code.

This commit is contained in:

View File

@@ -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 (canvas_x1, canvas_y1) = point_to_screen_space(p1x, p1y);
let (canvas_x2, canvas_y2) = point_to_screen_space(p2x, p2y);
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 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);
},
}
context.stroke();
}