Areaed!
This commit is contained in:
parent
3324dcacb4
commit
6f77a31727
224
src/bin/flat.rs
224
src/bin/flat.rs
|
|
@ -1,3 +1,4 @@
|
|||
use std::collections::HashMap;
|
||||
use flo_draw::*;
|
||||
use flo_canvas::*;
|
||||
use glam::*;
|
||||
|
|
@ -6,33 +7,147 @@ use riemann::{Decomp2, Metric, trace_iter};
|
|||
#[cfg(test)]
|
||||
use approx::assert_abs_diff_eq;
|
||||
|
||||
const DT: f32 = 0.1;
|
||||
|
||||
pub fn main() {
|
||||
let space = Coil {
|
||||
scale: 3.0,
|
||||
r: 300.0,
|
||||
w: 50.0,
|
||||
m: 10.0,
|
||||
};
|
||||
let space = Rect {
|
||||
inner_radius: 30.0,
|
||||
outer_radius: 50.0,
|
||||
internal_halflength: 100.0,
|
||||
external_halflength: 300.0,
|
||||
};
|
||||
with_2d_graphics(move || {
|
||||
let canvas = create_drawing_window("Refraction");
|
||||
canvas.draw(|gc| {
|
||||
let space = Coil {
|
||||
scale: 3.0,
|
||||
r: 300.0,
|
||||
w: 50.0,
|
||||
m: 10.0,
|
||||
};
|
||||
let tube = Rect {
|
||||
inner_radius: 30.0,
|
||||
outer_radius: 50.0,
|
||||
internal_halflength: 100.0,
|
||||
external_halflength: 300.0,
|
||||
};
|
||||
let mut grid = Grid {
|
||||
hlines: vec![-tube.external_halflength, tube.external_halflength],
|
||||
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);
|
||||
space.render(gc);
|
||||
tube.render(gc);
|
||||
gc.line_width(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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
|
||||
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 {
|
||||
for (k, &split) in splits.iter().enumerate() {
|
||||
if val < split {
|
||||
return k;
|
||||
}
|
||||
}
|
||||
splits.len()
|
||||
}
|
||||
|
||||
fn draw_ray_2(gc: &mut Vec<Draw>, space: &impl Metric, grid: &Grid, base: Vec2, dir: Vec2) {
|
||||
let dir = space.globalize(base, dir);
|
||||
gc.new_path();
|
||||
gc.move_to(base.x, base.y);
|
||||
let dt = DT;
|
||||
let mut p = base;
|
||||
let mut v = space.normalize(base, dir);
|
||||
for _ in 0..10000 {
|
||||
let a: Vec2 = -riemann::convolute(riemann::krist(space, p), v);
|
||||
v = v + a * dt;
|
||||
p = p + v * dt;
|
||||
gc.line_to(p.x, p.y);
|
||||
if p.abs().cmpgt(Vec2::splat(1000.0)).any() {
|
||||
break;
|
||||
}
|
||||
let i = find_bucket(p.x, grid.vlines.as_slice());
|
||||
let j = find_bucket(p.y, grid.hlines.as_slice());
|
||||
if let Some(cell) = grid.cells.get(&(i, j)) {
|
||||
gc.stroke();
|
||||
gc.new_dash_pattern();
|
||||
gc.dash_length(6.0);
|
||||
gc.new_path();
|
||||
gc.move_to(p.x, p.y);
|
||||
let mut ray = cell.ray_to_local(Ray { pos: p, dir: v });
|
||||
while cell.is_inside(ray.pos) && !ray.pos.abs().cmpgt(Vec2::splat(1000.0)).any() {
|
||||
ray = Ray { pos: ray.pos + ray.dir * dt, dir: ray.dir };
|
||||
p = cell.pos_to_global(ray.pos);
|
||||
gc.line_to(p.x, p.y);
|
||||
}
|
||||
Ray { pos: p, dir: v } = cell.ray_to_global(ray);
|
||||
gc.stroke();
|
||||
gc.new_dash_pattern();
|
||||
gc.new_path();
|
||||
gc.move_to(p.x, p.y);
|
||||
}
|
||||
}
|
||||
gc.stroke();
|
||||
}
|
||||
|
||||
fn draw_fan_2(gc: &mut Vec<Draw>, space: &impl Metric, grid: &Grid, base: Vec2, dir: Vec2, spread: f32) {
|
||||
let dir = dir.normalize();
|
||||
let v = vec2(-dir.y, dir.x);
|
||||
for y in itertools_num::linspace(-spread, spread, 101) {
|
||||
draw_ray_2(gc, space, grid, base, dir + y * v);
|
||||
}
|
||||
}
|
||||
|
||||
fn draw_ray(gc: &mut Vec<Draw>, space: &impl Metric, base: Vec2, dir: Vec2) {
|
||||
let dir = space.globalize(base, dir);
|
||||
gc.new_path();
|
||||
gc.move_to(base.x, base.y);
|
||||
for pt in trace_iter(space, base, dir, 1.0).take(10000) {
|
||||
for pt in trace_iter(space, base, dir, DT).take(10000) {
|
||||
gc.line_to(pt.x, pt.y);
|
||||
if pt.abs().cmpgt(Vec2::splat(1000.0)).any() {
|
||||
break;
|
||||
|
|
@ -79,11 +194,6 @@ impl Renderable for Rect {
|
|||
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, -0.5 * self.internal_halflength), vec2(1.0, 1.0), 1.0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -112,6 +222,78 @@ impl Metric for Coil {
|
|||
}
|
||||
}
|
||||
|
||||
struct Ray {
|
||||
pos: Vec2,
|
||||
dir: Vec2,
|
||||
}
|
||||
|
||||
struct Grid {
|
||||
hlines: Vec<f32>,
|
||||
vlines: Vec<f32>,
|
||||
cells: HashMap<(usize, usize), Box<dyn FlatCell>>,
|
||||
}
|
||||
|
||||
trait FlatCell: std::fmt::Debug {
|
||||
fn pos_to_global(&self, pos: Vec2) -> Vec2;
|
||||
fn pos_to_local(&self, pos: Vec2) -> Vec2;
|
||||
fn ray_to_global(&self, ray: Ray) -> Ray;
|
||||
fn ray_to_local(&self, ray: Ray) -> Ray;
|
||||
|
||||
fn is_inside(&self, pos: Vec2) -> bool {
|
||||
let bnd = self.local_bounds();
|
||||
pos.cmpge(bnd.0).all() && pos.cmple(bnd.1).all()
|
||||
}
|
||||
fn local_bounds(&self) -> (Vec2, Vec2);
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct FlatRect {
|
||||
min: Vec2,
|
||||
max: Vec2,
|
||||
}
|
||||
|
||||
impl FlatCell for FlatRect {
|
||||
fn pos_to_global(&self, pos: Vec2) -> Vec2 { pos }
|
||||
fn pos_to_local(&self, pos: Vec2) -> Vec2 { pos }
|
||||
fn ray_to_global(&self, ray: Ray) -> Ray { ray }
|
||||
fn ray_to_local(&self, ray: Ray) -> Ray { ray }
|
||||
fn local_bounds(&self) -> (Vec2, Vec2) { (self.min, self.max) }
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct RectInside {
|
||||
rect: Rect,
|
||||
}
|
||||
|
||||
impl FlatCell for RectInside {
|
||||
fn pos_to_global(&self, pos: Vec2) -> Vec2 {
|
||||
vec2(pos.x, self.rect.x(pos.y))
|
||||
}
|
||||
|
||||
fn pos_to_local(&self, pos: Vec2) -> Vec2 {
|
||||
vec2(pos.x, self.rect.u(pos.y))
|
||||
}
|
||||
|
||||
fn ray_to_global(&self, ray: Ray) -> Ray {
|
||||
Ray {
|
||||
pos: self.pos_to_global(ray.pos),
|
||||
dir: vec2(ray.dir.x, self.rect.dx(ray.pos.y, ray.dir.y)),
|
||||
}
|
||||
}
|
||||
|
||||
fn ray_to_local(&self, ray: Ray) -> Ray {
|
||||
Ray {
|
||||
pos: self.pos_to_local(ray.pos),
|
||||
dir: vec2(ray.dir.x, self.rect.du(ray.pos.y, ray.dir.y)),
|
||||
}
|
||||
}
|
||||
|
||||
fn local_bounds(&self) -> (Vec2, Vec2) {
|
||||
(vec2(-self.rect.inner_radius, -self.rect.internal_halflength), vec2(self.rect.inner_radius, self.rect.internal_halflength))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
struct Rect {
|
||||
outer_radius: f32,
|
||||
inner_radius: f32,
|
||||
|
|
@ -275,7 +457,7 @@ mod riemann {
|
|||
}
|
||||
}
|
||||
|
||||
fn krist(space: &impl Metric, pos: Vec2) -> Tens2 {
|
||||
pub fn krist(space: &impl Metric, pos: Vec2) -> Tens2 {
|
||||
// Γ^i_k_l = .5 * g^i^m * (g_m_k,l + g_m_l,k - g_k_l,m)
|
||||
let g = &space.invmetric(pos); // с верхними индексами
|
||||
let d = space.dmetric(pos);
|
||||
|
|
@ -294,7 +476,7 @@ mod riemann {
|
|||
]
|
||||
}
|
||||
|
||||
fn convolute(t: Tens2, v: Vec2) -> Vec2 {
|
||||
pub fn convolute(t: Tens2, v: Vec2) -> Vec2 {
|
||||
vec2(
|
||||
v.dot(t[0] * v),
|
||||
v.dot(t[1] * v),
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user