use Implicit;
use super::geom::{Line, Point, Vector};
pub enum MarchResult {
None,
One(Line),
OneDebug(Line),
Two(Line, Line),
Debug
}
const A: Vector = Vector { x: -0.5, y: -0.5 };
const B: Vector = Vector { x: 0.5, y: -0.5 };
const C: Vector = Vector { x: 0.5, y: 0.5 };
const D: Vector = Vector { x: -0.5, y: 0.5 };
const N: Vector = Vector { x: 0.0, y: -0.5 };
const S: Vector = Vector { x: 0.0, y: 0.5 };
const E: Vector = Vector { x: 0.5, y: 0.0 };
const W: Vector = Vector { x: -0.5, y: 0.0 };
#[inline(always)]
fn n(distance: f32, point: Point, how_much: f32) -> Point {
let mut result = N * distance + point;
result.x += how_much;
result
}
#[inline(always)]
fn s(distance: f32, point: Point, how_much: f32) -> Point {
let mut result = S * distance + point;
result.x += how_much;
result
}
#[inline(always)]
fn e(distance: f32, point: Point, how_much: f32) -> Point {
let mut result = E * distance + point;
result.y += how_much;
result
}
#[inline(always)]
fn w(distance: f32, point: Point, how_much: f32) -> Point {
let mut result = W * distance + point;
result.y += how_much;
result
}
fn lerp(fa: f32, fb: f32, dist: f32) -> f32 {
-dist / 2.0 + dist * ((-fa) / (fb - fa))
}
pub fn march<I: Implicit>(i: &I, p: Point, dist: f32) -> MarchResult {
let sa = A * dist + p;
let sb = B * dist + p;
let sc = C * dist + p;
let sd = D * dist + p;
let sra = i.sample(sa);
let srb = i.sample(sb);
let src = i.sample(sc);
let srd = i.sample(sd);
let a_on = sra <= 0.0;
let b_on = srb <= 0.0;
let c_on = src <= 0.0;
let d_on = srd <= 0.0;
match (a_on, b_on, c_on, d_on) {
(false, false, false, false) => MarchResult::None,
(false, false, false, true) => {
let da = lerp(sra, srd, dist);
let dc = lerp(src, srd, dist);
MarchResult::One(Line(w(dist, p, da), s(dist, p, -dc)))
},
(false, false, true, false) => {
let db = lerp(src, srb, dist);
let dd = lerp(srd, src, dist);
MarchResult::One(Line(s(dist, p, dd), e(dist, p, -db)))
},
(false, false, true, true) => {
let da = lerp(sra, srd, dist);
let db = lerp(srb, src, dist);
MarchResult::One(Line(w(dist, p, da), e(dist, p, db)))
},
(false, true, false, false) => {
let da = lerp(sra, srb, dist);
let db = lerp(srb, src, dist);
MarchResult::One(Line(n(dist, p, da), e(dist, p, db)))
},
(false, true, false, true) => {
let srm = i.sample(p);
let m_on = srm <= 0.0;
if m_on {
MarchResult::Two(
Line(w(dist, p, 0.0), n(dist, p, 0.0)),
Line(s(dist, p, 0.0), e(dist, p, 0.0)))
}
else {
MarchResult::Two(
Line(w(dist, p, 0.0), s(dist, p, 0.0)),
Line(n(dist, p, 0.0), e(dist, p, 0.0)))
}
},
(false, true, true, false) => {
let da = lerp(srb, sra, dist);
let dd = lerp(src, srd, dist);
MarchResult::One(Line(n(dist, p, -da), s(dist, p, -dd)))
},
(false, true, true, true) => {
let dc = lerp(sra, srb, dist);
let dd = lerp(sra, srd, dist);
MarchResult::One(Line(w(dist, p, dd), n(dist, p, dc)))
},
(true, false, false, false) => {
let db = lerp(sra, srb, dist);
let dd = lerp(sra, srd, dist);
MarchResult::One(Line(w(dist, p, dd), n(dist, p, db)))
},
(true, false, false, true) => {
let da = lerp(srb, sra, dist);
let dd = lerp(src, srd, dist);
MarchResult::One(Line(n(dist, p, -da), s(dist, p, -dd)))
},
(true, false, true, false) => {
let srm = i.sample(p);
let m_on = srm <= 0.0;
if m_on {
MarchResult::Two(
Line(n(dist, p, 0.0), e(dist, p, 0.0)),
Line(w(dist, p, 0.0), s(dist, p, 0.0)))
}
else {
MarchResult::Two(
Line(w(dist, p, 0.0), n(dist, p, 0.0)),
Line(s(dist, p, 0.0), e(dist, p, 0.0)))
}
},
(true, false, true, true) => {
let da = lerp(sra, srb, dist);
let dc = lerp(src, srb, dist);
MarchResult::One(Line(n(dist, p, da), e(dist, p, -dc)))
},
(true, true, false, false) => {
let da = lerp(sra, srd, dist);
let db = lerp(srb, src, dist);
MarchResult::One(Line(w(dist, p, da), e(dist, p, db)))
},
(true, true, false, true) => {
let db = lerp(srb, src, dist);
let dd = lerp(srd, src, dist);
MarchResult::One(Line(s(dist, p, dd), e(dist, p, db)))
},
(true, true, true, false) => {
let da = lerp(sra, srd, dist);
let dd = lerp(srd, src, dist);
MarchResult::One(Line(w(dist, p, da), s(dist, p, dd)))
},
(true, true, true, true) => {
MarchResult::None
},
}
}