Split the geometry finding code from the drawing code.
This commit is contained in:
87
src/lib.rs
87
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();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user