Simplify
This commit is contained in:
parent
44efe70348
commit
408bd2c936
180
src/bin/flat.rs
180
src/bin/flat.rs
|
|
@ -1,8 +1,9 @@
|
||||||
use std::collections::HashMap;
|
|
||||||
use flo_draw::*;
|
use flo_draw::*;
|
||||||
use flo_canvas::*;
|
use flo_canvas::*;
|
||||||
use glam::*;
|
use glam::*;
|
||||||
use riemann::{Decomp2, Metric, trace_iter};
|
use riemann::{Decomp2, Metric, trace_iter};
|
||||||
|
use shape::Shape;
|
||||||
|
use Subspace::{Boundary, Inner, Outer};
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
use approx::assert_abs_diff_eq;
|
use approx::assert_abs_diff_eq;
|
||||||
|
|
@ -13,133 +14,115 @@ pub fn main() {
|
||||||
with_2d_graphics(move || {
|
with_2d_graphics(move || {
|
||||||
let canvas = create_drawing_window("Refraction");
|
let canvas = create_drawing_window("Refraction");
|
||||||
canvas.draw(|gc| {
|
canvas.draw(|gc| {
|
||||||
let space = Coil {
|
|
||||||
scale: 3.0,
|
|
||||||
r: 300.0,
|
|
||||||
w: 50.0,
|
|
||||||
m: 10.0,
|
|
||||||
};
|
|
||||||
let tube = Rect {
|
let tube = Rect {
|
||||||
inner_radius: 30.0,
|
inner_radius: 30.0,
|
||||||
outer_radius: 50.0,
|
outer_radius: 50.0,
|
||||||
internal_halflength: 100.0,
|
internal_halflength: 100.0,
|
||||||
external_halflength: 300.0,
|
external_halflength: 300.0,
|
||||||
};
|
};
|
||||||
let mut grid = Grid {
|
|
||||||
hlines: vec![-tube.external_halflength, tube.external_halflength],
|
let space = Space { rect: tube };
|
||||||
vlines: vec![-tube.outer_radius, -tube.inner_radius, tube.inner_radius, tube.outer_radius],
|
|
||||||
cells: HashMap::new(),
|
|
||||||
};
|
|
||||||
fn take(k: i32, data: &[f32]) -> f32 {
|
|
||||||
if k < 0 {
|
|
||||||
-f32::INFINITY
|
|
||||||
} else if k as usize >= data.len() {
|
|
||||||
f32::INFINITY
|
|
||||||
} else {
|
|
||||||
data[k as usize]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (i, j) in [(0, 0), (1, 0), (2, 0), (3, 0), (4, 0), (0, 1), (4, 1), (0, 2), (1, 2), (2, 2), (3, 2), (4, 2)] {
|
|
||||||
grid.cells.insert((i as usize, j as usize),
|
|
||||||
Box::new(FlatRect {
|
|
||||||
min: vec2(take(i - 1, grid.vlines.as_slice()), take(j - 1, grid.hlines.as_slice())),
|
|
||||||
max: vec2(take(i, grid.vlines.as_slice()), take(j, grid.hlines.as_slice())),
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
grid.cells.insert((2, 1), Box::new(RectInside { rect: tube }));
|
|
||||||
println!("{:?}", grid.cells);
|
|
||||||
gc.canvas_height(1000.0);
|
gc.canvas_height(1000.0);
|
||||||
tube.render(gc);
|
tube.render(gc);
|
||||||
gc.line_width(0.5);
|
gc.line_width(0.5);
|
||||||
gc.stroke_color(Color::Rgba(1.0, 0.5, 0.0, 0.5));
|
gc.stroke_color(Color::Rgba(1.0, 0.5, 0.0, 0.5));
|
||||||
draw_fan(gc, &tube, vec2(-500.0, 0.0), vec2(1.0, 0.0), 1.0);
|
draw_fan(gc, &tube, vec2(-500.0, 0.0), vec2(1.0, 0.0), 1.0);
|
||||||
gc.stroke_color(Color::Rgba(1.0, 0.5, 0.0, 1.0));
|
gc.stroke_color(Color::Rgba(1.0, 0.5, 0.0, 1.0));
|
||||||
draw_fan_2(gc, &tube, &grid, vec2(-500.0, 0.0), vec2(1.0, 0.0), 1.0);
|
draw_fan_2(gc, &space, vec2(-500.0, 0.0), vec2(1.0, 0.0), 1.0);
|
||||||
gc.stroke_color(Color::Rgba(0.0, 0.5, 1.0, 0.5));
|
gc.stroke_color(Color::Rgba(0.0, 0.5, 1.0, 0.5));
|
||||||
draw_fan(gc, &tube, vec2(0.0, -0.5 * tube.internal_halflength), vec2(1.0, 1.0), 1.0);
|
draw_fan(gc, &tube, vec2(0.0, -0.5 * tube.internal_halflength), vec2(1.0, 1.0), 1.0);
|
||||||
gc.stroke_color(Color::Rgba(0.0, 0.5, 1.0, 1.0));
|
gc.stroke_color(Color::Rgba(0.0, 0.5, 1.0, 1.0));
|
||||||
draw_fan_2(gc, &tube, &grid, vec2(0.0, -0.5 * tube.internal_halflength), vec2(1.0, 1.0), 1.0);
|
draw_fan_2(gc, &space, vec2(0.0, -0.5 * tube.internal_halflength), vec2(1.0, 1.0), 1.0);
|
||||||
|
|
||||||
gc.new_path();
|
|
||||||
for ((i, j), cell) in &grid.cells {
|
|
||||||
let (a, b) = cell.local_bounds();
|
|
||||||
gc.rect(a.x.clamp(-1000.0, 1000.0), a.y.clamp(-1000.0, 1000.0), b.x.clamp(-1000.0, 1000.0), b.y.clamp(-1000.0, 1000.0));
|
|
||||||
}
|
|
||||||
gc.fill_color(Color::Rgba(0.0, 1.0, 0.0, 0.3));
|
|
||||||
gc.fill();
|
|
||||||
|
|
||||||
gc.new_dash_pattern();
|
|
||||||
gc.dash_length(6.0);
|
|
||||||
gc.new_dash_pattern();
|
|
||||||
gc.new_path();
|
|
||||||
gc.stroke_color(Color::Rgba(0.0, 0.0, 0.0, 0.5));
|
|
||||||
gc.line_width(1.0);
|
|
||||||
for hline in grid.hlines {
|
|
||||||
gc.move_to(-1000.0, hline);
|
|
||||||
gc.line_to(1000.0, hline);
|
|
||||||
}
|
|
||||||
for vline in grid.vlines {
|
|
||||||
gc.move_to(vline, -1000.0);
|
|
||||||
gc.line_to(vline, 1000.0);
|
|
||||||
}
|
|
||||||
gc.stroke();
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_bucket(val: f32, splits: &[f32]) -> usize {
|
struct Space {
|
||||||
for (k, &split) in splits.iter().enumerate() {
|
rect: Rect,
|
||||||
if val < split {
|
|
||||||
return k;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
splits.len()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_ray_2(gc: &mut Vec<Draw>, space: &impl Metric, grid: &Grid, base: Vec2, dir: Vec2) {
|
#[derive(PartialEq, Eq)]
|
||||||
let dir = space.globalize(base, dir);
|
enum Subspace {
|
||||||
|
Outer,
|
||||||
|
Boundary,
|
||||||
|
Inner,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Space {
|
||||||
|
fn which_subspace(&self, pt: Vec2) -> Subspace {
|
||||||
|
if pt.y.abs() > self.rect.external_halflength {
|
||||||
|
Outer
|
||||||
|
} else if pt.x.abs() > self.rect.outer_radius {
|
||||||
|
Outer
|
||||||
|
} else if pt.x.abs() > self.rect.inner_radius {
|
||||||
|
Boundary
|
||||||
|
} else {
|
||||||
|
Inner
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn draw_ray_2(gc: &mut Vec<Draw>, space: &Space, base: Vec2, dir: Vec2) {
|
||||||
|
let dir = space.rect.globalize(base, dir);
|
||||||
gc.new_path();
|
gc.new_path();
|
||||||
gc.move_to(base.x, base.y);
|
gc.move_to(base.x, base.y);
|
||||||
let dt = DT;
|
let dt = DT;
|
||||||
let mut p = base;
|
let mut p = base;
|
||||||
let mut v = space.normalize(base, dir);
|
let mut v = space.rect.normalize(base, dir);
|
||||||
for _ in 0..10000 {
|
for _ in 0..10000 {
|
||||||
let a: Vec2 = -riemann::convolute(riemann::krist(space, p), v);
|
let a: Vec2 = -riemann::convolute(riemann::krist(&space.rect, p), v);
|
||||||
v = v + a * dt;
|
v = v + a * dt;
|
||||||
p = p + v * dt;
|
p = p + v * dt;
|
||||||
gc.line_to(p.x, p.y);
|
gc.line_to(p.x, p.y);
|
||||||
if p.abs().cmpgt(Vec2::splat(1000.0)).any() {
|
if p.abs().cmpgt(Vec2::splat(1000.0)).any() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
let i = find_bucket(p.x, grid.vlines.as_slice());
|
let sub = space.which_subspace(p);
|
||||||
let j = find_bucket(p.y, grid.hlines.as_slice());
|
if sub == Boundary {
|
||||||
if let Some(cell) = grid.cells.get(&(i, j)) {
|
continue;
|
||||||
|
}
|
||||||
gc.stroke();
|
gc.stroke();
|
||||||
gc.new_dash_pattern();
|
gc.new_dash_pattern();
|
||||||
gc.dash_length(6.0);
|
gc.dash_length(6.0);
|
||||||
gc.new_path();
|
gc.new_path();
|
||||||
gc.move_to(p.x, p.y);
|
gc.move_to(p.x, p.y);
|
||||||
|
match sub {
|
||||||
|
Inner => {
|
||||||
|
let cell = RectInside { rect: space.rect };
|
||||||
let ray = cell.ray_to_local(Ray { pos: p, dir: v });
|
let ray = cell.ray_to_local(Ray { pos: p, dir: v });
|
||||||
let Some(ray) = cell.to_boundary(ray) else {
|
let Some(ray) = cell.to_boundary(ray) else {
|
||||||
break;
|
panic!("Can't get outta here!");
|
||||||
};
|
};
|
||||||
Ray { pos: p, dir: v } = cell.ray_to_global(ray);
|
Ray { pos: p, dir: v } = cell.ray_to_global(ray);
|
||||||
|
}
|
||||||
|
Outer => {
|
||||||
|
let cell = basic_shapes::Rect { size: vec2(space.rect.outer_radius, space.rect.external_halflength) };
|
||||||
|
let Some(dist) = cell.trace_into(Ray { pos: p, dir: v }) else {
|
||||||
|
p += v * 1000.0;
|
||||||
|
gc.line_to(p.x, p.y);
|
||||||
|
gc.stroke();
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
p += v * dist;
|
||||||
|
}
|
||||||
|
Boundary => panic!(),
|
||||||
|
}
|
||||||
gc.line_to(p.x, p.y);
|
gc.line_to(p.x, p.y);
|
||||||
gc.stroke();
|
gc.stroke();
|
||||||
gc.new_dash_pattern();
|
gc.new_dash_pattern();
|
||||||
gc.new_path();
|
gc.new_path();
|
||||||
gc.move_to(p.x, p.y);
|
gc.move_to(p.x, p.y);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
gc.stroke();
|
gc.stroke();
|
||||||
gc.new_dash_pattern();
|
gc.new_dash_pattern();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_fan_2(gc: &mut Vec<Draw>, space: &impl Metric, grid: &Grid, base: Vec2, dir: Vec2, spread: f32) {
|
fn draw_fan_2(gc: &mut Vec<Draw>, space: &Space, base: Vec2, dir: Vec2, spread: f32) {
|
||||||
let dir = dir.normalize();
|
let dir = dir.normalize();
|
||||||
let v = vec2(-dir.y, dir.x);
|
let v = vec2(-dir.y, dir.x);
|
||||||
for y in itertools_num::linspace(-spread, spread, 101) {
|
for y in itertools_num::linspace(-spread, spread, 101) {
|
||||||
draw_ray_2(gc, space, grid, base, dir + y * v);
|
draw_ray_2(gc, space, base, dir + y * v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -168,24 +151,6 @@ trait Renderable {
|
||||||
fn render(&self, gc: &mut Vec<Draw>);
|
fn render(&self, gc: &mut Vec<Draw>);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Renderable for Coil {
|
|
||||||
fn render(&self, gc: &mut Vec<Draw>) {
|
|
||||||
gc.new_path();
|
|
||||||
gc.circle(0.0, 0.0, self.r + self.w + self.m);
|
|
||||||
gc.circle(0.0, 0.0, self.r + self.w);
|
|
||||||
gc.circle(0.0, 0.0, self.r - self.w);
|
|
||||||
gc.circle(0.0, 0.0, self.r - self.w - self.m);
|
|
||||||
gc.winding_rule(WindingRule::EvenOdd);
|
|
||||||
gc.fill_color(Color::Rgba(0.8, 0.8, 0.8, 1.0));
|
|
||||||
gc.fill();
|
|
||||||
gc.line_width(0.5);
|
|
||||||
gc.stroke_color(Color::Rgba(1.0, 0.5, 0.0, 1.0));
|
|
||||||
draw_fan(gc, self, vec2(-500.0, 0.0), vec2(1.0, 0.0), 1.0);
|
|
||||||
gc.stroke_color(Color::Rgba(0.0, 0.5, 1.0, 1.0));
|
|
||||||
draw_fan(gc, self, vec2(0.0, self.r), vec2(1.0, 0.0), 1.0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Renderable for Rect {
|
impl Renderable for Rect {
|
||||||
fn render(&self, gc: &mut Vec<Draw>) {
|
fn render(&self, gc: &mut Vec<Draw>) {
|
||||||
gc.new_path();
|
gc.new_path();
|
||||||
|
|
@ -197,31 +162,6 @@ impl Renderable for Rect {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Coil {
|
|
||||||
m: f32,
|
|
||||||
scale: f32,
|
|
||||||
r: f32,
|
|
||||||
w: f32,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Metric for Coil {
|
|
||||||
fn halfmetric(&self, pos: Vec2) -> Decomp2 {
|
|
||||||
let r = pos.length();
|
|
||||||
let dir = pos.normalize();
|
|
||||||
|
|
||||||
let s = smoothbox(r, vec2(self.r - self.w, self.r + self.w), self.m);
|
|
||||||
let t = 1.0.lerp(self.r / r / self.scale, s);
|
|
||||||
|
|
||||||
Decomp2 {
|
|
||||||
ortho: Mat2::from_cols_array(&[
|
|
||||||
dir.x, -dir.y,
|
|
||||||
dir.y, dir.x,
|
|
||||||
]),
|
|
||||||
diag: vec2(1.0, t),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
struct Ray {
|
struct Ray {
|
||||||
pos: Vec2,
|
pos: Vec2,
|
||||||
|
|
@ -380,12 +320,6 @@ mod shape {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Grid {
|
|
||||||
hlines: Vec<f32>,
|
|
||||||
vlines: Vec<f32>,
|
|
||||||
cells: HashMap<(usize, usize), Box<dyn FlatCell>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
trait FlatCell: std::fmt::Debug {
|
trait FlatCell: std::fmt::Debug {
|
||||||
fn pos_to_global(&self, pos: Vec2) -> Vec2;
|
fn pos_to_global(&self, pos: Vec2) -> Vec2;
|
||||||
fn pos_to_local(&self, pos: Vec2) -> Vec2;
|
fn pos_to_local(&self, pos: Vec2) -> Vec2;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user