Split the geometry finding code from the drawing code.
This commit is contained in:
91
src/lib.rs
91
src/lib.rs
@@ -63,6 +63,11 @@ struct Ship {
|
|||||||
_orientation: CGA,
|
_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 {
|
fn point_to_cga(x: f64, y: f64) -> CGA {
|
||||||
let x_vec = CGA::e1();
|
let x_vec = CGA::e1();
|
||||||
let y_vec = CGA::e2();
|
let y_vec = CGA::e2();
|
||||||
@@ -100,54 +105,56 @@ fn draw_point(context: &CanvasRenderingContext2d, point: &CGA) {
|
|||||||
context.fill();
|
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) {
|
fn draw_line(context: &CanvasRenderingContext2d, line: &CGA) {
|
||||||
context.begin_path();
|
context.begin_path();
|
||||||
context.set_stroke_style_str(GREEN);
|
context.set_stroke_style_str(GREEN);
|
||||||
|
|
||||||
//Naively assume we are given a valid line/circle
|
let geometry = get_geometry(line);
|
||||||
let n_bar = CGA::e4() - CGA::e5();
|
match geometry {
|
||||||
let n_vec = CGA::e4() + CGA::e5();
|
Geometry::Circle(x,y,r) => {
|
||||||
let dual = line.Dual();
|
let (canvas_x, canvas_y) = point_to_screen_space(x, y);
|
||||||
|
|
||||||
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 canvas_r = r*RADIUS;
|
let canvas_r = r*RADIUS;
|
||||||
context.arc(canvas_x, canvas_y, canvas_r, 0., TWO_PI).unwrap();
|
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();
|
context.stroke();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user