Added some utility functions and intersection testing.
This commit is contained in:
165
src/lib.rs
165
src/lib.rs
@@ -47,9 +47,9 @@ const BLUE: &str = "#0000ff";
|
|||||||
const SCALAR: usize = 0;
|
const SCALAR: usize = 0;
|
||||||
const E1: usize = 1;
|
const E1: usize = 1;
|
||||||
const E2: usize = 2;
|
const E2: usize = 2;
|
||||||
//const E3: usize = 3;
|
const E3: usize = 3;
|
||||||
//const E4: usize = 4;
|
const E4: usize = 4;
|
||||||
//const E5: usize = 5;
|
const E5: usize = 5;
|
||||||
const E12: usize = 6;
|
const E12: usize = 6;
|
||||||
const E13: usize = 7;
|
const E13: usize = 7;
|
||||||
const E14: usize = 8;
|
const E14: usize = 8;
|
||||||
@@ -60,22 +60,22 @@ const E25: usize = 12;
|
|||||||
const E34: usize = 13;
|
const E34: usize = 13;
|
||||||
const E35: usize = 14;
|
const E35: usize = 14;
|
||||||
const E45: usize = 15;
|
const E45: usize = 15;
|
||||||
//const E123: usize = 16;
|
const E123: usize = 16;
|
||||||
//const E124: usize = 17;
|
const E124: usize = 17;
|
||||||
//const E125: usize = 18;
|
const E125: usize = 18;
|
||||||
//const E134: usize = 19;
|
const E134: usize = 19;
|
||||||
//const E135: usize = 20;
|
const E135: usize = 20;
|
||||||
//const E145: usize = 21;
|
const E145: usize = 21;
|
||||||
//const E234: usize = 22;
|
const E234: usize = 22;
|
||||||
//const E235: usize = 23;
|
const E235: usize = 23;
|
||||||
//const E245: usize = 24;
|
const E245: usize = 24;
|
||||||
//const E345: usize = 25;
|
const E345: usize = 25;
|
||||||
//const E1234: usize = 26;
|
const E1234: usize = 26;
|
||||||
//const E1235: usize = 27;
|
const E1235: usize = 27;
|
||||||
//const E1245: usize = 28;
|
const E1245: usize = 28;
|
||||||
//const E1345: usize = 29;
|
const E1345: usize = 29;
|
||||||
//const E2345: usize = 30;
|
const E2345: usize = 30;
|
||||||
//const E12345: usize = 31;
|
const E12345: usize = 31;
|
||||||
|
|
||||||
const DRAG: f64 = 1.;
|
const DRAG: f64 = 1.;
|
||||||
const ACCEL_STR: f64 = 1.;
|
const ACCEL_STR: f64 = 1.;
|
||||||
@@ -352,6 +352,92 @@ fn _get_hyperbolic_translation(vec: &CGA) -> CGA {
|
|||||||
t
|
t
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum CircleIntersection {
|
||||||
|
Two_Points(CGA, CGA),
|
||||||
|
One_Point(CGA),
|
||||||
|
None,
|
||||||
|
}
|
||||||
|
|
||||||
|
/*fn get_circle_intersection(circle_1: &CGA, circle_2: &CGA) -> CircleIntersection {
|
||||||
|
if !circle_intersection(circle_1, circle_2) {
|
||||||
|
return CircleIntersection::None;
|
||||||
|
}
|
||||||
|
let n = CGA::e4() + CGA::e5();
|
||||||
|
}*/
|
||||||
|
|
||||||
|
fn circle_intersection(circle_1: &CGA, circle_2: &CGA) -> bool {
|
||||||
|
let circle_1 = grade_selection(circle_1, 4);
|
||||||
|
let circle_2 = grade_selection(circle_2, 4);
|
||||||
|
let meet = circle_1 & circle_2;
|
||||||
|
let sqr = &meet * &meet;
|
||||||
|
let mag = magnitude(&sqr);
|
||||||
|
if mag < ERROR {
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn line_intersection(line_1: &CGA, line_2: &CGA) -> bool {
|
||||||
|
let line_1 = grade_selection(line_1, 4);
|
||||||
|
let line_2 = grade_selection(line_2, 4);
|
||||||
|
let meet = line_1 & line_2;
|
||||||
|
let mag = magnitude(&meet);
|
||||||
|
if mag < ERROR {
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_line_intersection(line_1: &CGA, line_2: &CGA) -> Option<CGA> {
|
||||||
|
if !line_intersection(line_1, line_2) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let n = CGA::e4() + CGA::e5();
|
||||||
|
let x = CGA::up(0., 0., 0.); //Pick an arbitrary point
|
||||||
|
let l_1_tick = line_2 * line_1 * line_2; //reflect line_1 by line_2
|
||||||
|
let l_1_2tick = line_1 - l_1_tick; //bisector of line_1 and its reflection
|
||||||
|
let x_tick = &l_1_2tick * &x * & l_1_2tick; //reflection of x in the bisector
|
||||||
|
let x_2tick = 0.5*x + 0.5*&x_tick; //midpoint, on the bisector
|
||||||
|
let x_3tick = line_2*&x_2tick*line_2; //Reflection of midpoint in line_2
|
||||||
|
let p_tick = 0.5*&x_2tick + 0.5 * x_3tick; //Intersection point of lines, but with extra n component.
|
||||||
|
let dot = &p_tick | &n;
|
||||||
|
let dot_sqr = dot[SCALAR]*dot[SCALAR];
|
||||||
|
let p = -1.*&p_tick*&n*&p_tick*(0.5/dot_sqr); //Get the point with the correct n component.
|
||||||
|
Some(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn grade_selection(multi: &CGA, grade: usize) -> CGA {
|
||||||
|
match grade {
|
||||||
|
0 => { CGA::new(multi[SCALAR], SCALAR) },
|
||||||
|
1 => { multi[E1]*CGA::e1() + multi[E2]*CGA::e2() + multi[E3]*CGA::e3() + multi[E4]*CGA::e4() + multi[E5]*CGA::e5() },
|
||||||
|
2 => { multi[E12]*CGA::e12() + multi[E13]*CGA::e13() + multi[E14]*CGA::e14() + multi[E15]*CGA::e15()
|
||||||
|
+ multi[E23]*CGA::e23() + multi[E24]*CGA::e24() + multi[E25]*CGA::e25()
|
||||||
|
+ multi[E34]*CGA::e34() + multi[E35]*CGA::e35() + multi[E45]*CGA::e45() },
|
||||||
|
3 => { multi[E123]*CGA::e123() + multi[E124]*CGA::e124() + multi[E125]*CGA::e125() + multi[E134]*CGA::e134()
|
||||||
|
+ multi[E135]*CGA::e135() + multi[E145]*CGA::e145() + multi[E234]*CGA::e234() + multi[E235]*CGA::e235()
|
||||||
|
+ multi[E245]*CGA::e245() + multi[E345]*CGA::e345() },
|
||||||
|
4 => { multi[E1234]*CGA::e1234() + multi[E1235]*CGA::e1235() + multi[E1245]*CGA::e1245() + multi[E1345]*CGA::e1345()
|
||||||
|
+ multi[E2345]*CGA::e2345() },
|
||||||
|
5 => { multi[E12345]*CGA::e12345() }
|
||||||
|
_ => { CGA::zero() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn magnitude(multi: &CGA) -> f64 {
|
||||||
|
multi[SCALAR]*multi[SCALAR]
|
||||||
|
+ multi[E1]*multi[E1] + multi[E2]*multi[E2] + multi[E3]*multi[E3] + multi[E4]*multi[E4] + multi[E5]*multi[E5]
|
||||||
|
+ multi[E12]*multi[E12] + multi[E13]*multi[E13] + multi[E14]*multi[E14] + multi[E15]*multi[E15]
|
||||||
|
+ multi[E23]*multi[E23] + multi[E24]*multi[E24] + multi[E25]*multi[E25]
|
||||||
|
+ multi[E34]*multi[E34] + multi[E35]*multi[E35] + multi[E45]*multi[E45]
|
||||||
|
+ multi[E123]*multi[E123] + multi[E124]*multi[E124] + multi[E125]*multi[E125]
|
||||||
|
+ multi[E134]*multi[E134] + multi[E135]*multi[E135] + multi[E145]*multi[E145]
|
||||||
|
+ multi[E234]*multi[E234] + multi[E235]*multi[E235] + multi[E245]*multi[E245] + multi[E345]*multi[E345]
|
||||||
|
+ multi[E1234]*multi[E1234] + multi[E1235]*multi[E1235] + multi[E1245]*multi[E1245] + multi[E1345]*multi[E1345] + multi[E2345]*multi[E2345]
|
||||||
|
+ multi[E12345]*multi[E12345]
|
||||||
|
}
|
||||||
|
|
||||||
fn gen_hyperbolic_point(vec: &CGA) -> CGA {
|
fn gen_hyperbolic_point(vec: &CGA) -> CGA {
|
||||||
let vec_sqr = (vec * vec)[SCALAR];
|
let vec_sqr = (vec * vec)[SCALAR];
|
||||||
if vec_sqr >= 1. {
|
if vec_sqr >= 1. {
|
||||||
@@ -365,20 +451,7 @@ fn gen_hyperbolic_point(vec: &CGA) -> CGA {
|
|||||||
fn bivector_exponential(bivector: &CGA) -> CGA {
|
fn bivector_exponential(bivector: &CGA) -> CGA {
|
||||||
//Explicitly take only the bivector part.
|
//Explicitly take only the bivector part.
|
||||||
//The library doesn't provide a grade 2 selection.
|
//The library doesn't provide a grade 2 selection.
|
||||||
let a = bivector[E12];
|
let bivector = grade_selection(bivector, 2);
|
||||||
let b = bivector[E13];
|
|
||||||
let c = bivector[E14];
|
|
||||||
let d = bivector[E15];
|
|
||||||
let e = bivector[E23];
|
|
||||||
let f = bivector[E24];
|
|
||||||
let g = bivector[E25];
|
|
||||||
let h = bivector[E34];
|
|
||||||
let i = bivector[E35];
|
|
||||||
let j = bivector[E45];
|
|
||||||
|
|
||||||
let bivector = a*CGA::e12() + b*CGA::e13() + c*CGA::e14()
|
|
||||||
+ d*CGA::e15() + e*CGA::e23() + f*CGA::e24() + g*CGA::e25()
|
|
||||||
+ h*CGA::e34() + i *CGA::e35() + j*CGA::e45();
|
|
||||||
let sqr = (&bivector*&bivector)[SCALAR];
|
let sqr = (&bivector*&bivector)[SCALAR];
|
||||||
if sqr.abs() < ERROR {
|
if sqr.abs() < ERROR {
|
||||||
CGA::new(1., SCALAR) + bivector
|
CGA::new(1., SCALAR) + bivector
|
||||||
@@ -396,22 +469,28 @@ struct Asteroid {
|
|||||||
vel: CGA,
|
vel: CGA,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn circle_from_coords(x: f64, y: f64, r: f64) -> CGA {
|
||||||
|
let (a_x, a_y) = (x + r * 0.0_f64.cos(), y + r * 0.0_f64.sin());
|
||||||
|
let (b_x, b_y) = (x + r * 1.0_f64.cos(), y + r * 1.0_f64.sin());
|
||||||
|
let (c_x, c_y) = (x + r * 2.0_f64.cos(), y + r * 2.0_f64.sin());
|
||||||
|
let a = point_to_cga(a_x, a_y);
|
||||||
|
let b = point_to_cga(b_x, b_y);
|
||||||
|
let c = point_to_cga(c_x, c_y);
|
||||||
|
let circle = a^b^c^CGA::e3();
|
||||||
|
circle
|
||||||
|
}
|
||||||
|
|
||||||
impl Asteroid {
|
impl Asteroid {
|
||||||
fn new() -> Asteroid {
|
fn new() -> Asteroid {
|
||||||
let v = 0.1;
|
let v = 0.1;
|
||||||
let (v_x, v_y) = (v * 1.0_f64.cos(), v*1.0_f64.sin());
|
let (v_x, v_y) = (v * 1.0_f64.cos(), v*1.0_f64.sin());
|
||||||
let vel = v_x*CGA::e15() + v_y*CGA::e25();
|
let vel = v_x*CGA::e15() + v_y*CGA::e25();
|
||||||
Self::new_from_coords(0.0_f64, 0.0_f64, 0.1_f64, vel)
|
let circle = circle_from_coords(0., 0., 0.);
|
||||||
|
Asteroid { circle, vel }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_from_coords(x: f64, y: f64, r: f64, vel: CGA) -> Asteroid {
|
fn new_from_coords(x: f64, y: f64, r: f64, vel: CGA) -> Asteroid {
|
||||||
let (a_x, a_y) = (x + r * 0.0_f64.cos(), y + r * 0.0_f64.sin());
|
let circle = circle_from_coords(x, y, r);
|
||||||
let (b_x, b_y) = (x + r * 1.0_f64.cos(), y + r * 1.0_f64.sin());
|
|
||||||
let (c_x, c_y) = (x + r * 2.0_f64.cos(), y + r * 2.0_f64.sin());
|
|
||||||
let a = point_to_cga(a_x, a_y);
|
|
||||||
let b = point_to_cga(b_x, b_y);
|
|
||||||
let c = point_to_cga(c_x, c_y);
|
|
||||||
let circle = a^b^c^CGA::e3();
|
|
||||||
Asteroid { circle, vel }
|
Asteroid { circle, vel }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -433,6 +512,7 @@ pub struct Game {
|
|||||||
context: CanvasRenderingContext2d,
|
context: CanvasRenderingContext2d,
|
||||||
ship: Ship,
|
ship: Ship,
|
||||||
asteroids: Vec::<Asteroid>,
|
asteroids: Vec::<Asteroid>,
|
||||||
|
boundary: CGA,
|
||||||
keys: HashSet<String>,
|
keys: HashSet<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -463,9 +543,11 @@ impl Game {
|
|||||||
orientation: CGA::new(1., SCALAR),
|
orientation: CGA::new(1., SCALAR),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let boundary = circle_from_coords(0., 0., 0.99);
|
||||||
Game {
|
Game {
|
||||||
context: context,
|
context: context,
|
||||||
ship,
|
ship,
|
||||||
|
boundary,
|
||||||
asteroids: vec![Asteroid::new()],
|
asteroids: vec![Asteroid::new()],
|
||||||
keys: HashSet::new(),
|
keys: HashSet::new(),
|
||||||
}
|
}
|
||||||
@@ -479,6 +561,7 @@ impl Game {
|
|||||||
self.context.set_stroke_style_str(BLACK);
|
self.context.set_stroke_style_str(BLACK);
|
||||||
self.context.arc(CENTER_X, CENTER_Y, RADIUS, 0., TWO_PI).unwrap();
|
self.context.arc(CENTER_X, CENTER_Y, RADIUS, 0., TWO_PI).unwrap();
|
||||||
self.context.stroke();
|
self.context.stroke();
|
||||||
|
draw_line(&self.context, &self.boundary);
|
||||||
self.ship.draw(&self.context);
|
self.ship.draw(&self.context);
|
||||||
for asteroid in &self.asteroids {
|
for asteroid in &self.asteroids {
|
||||||
asteroid.draw(&self.context);
|
asteroid.draw(&self.context);
|
||||||
|
|||||||
Reference in New Issue
Block a user