Sketch a 5-5-4 near miss test assembly

This commit is contained in:
Aaron Fenyes 2025-08-23 12:40:11 -04:00
parent 8a0d81d707
commit 8bedb0baf7

View file

@ -1,5 +1,5 @@
use itertools::izip; use itertools::izip;
use std::{f64::consts::{FRAC_1_SQRT_2, PI}, rc::Rc}; use std::{f64::consts::{FRAC_1_SQRT_2, PI, SQRT_2}, rc::Rc};
use nalgebra::Vector3; use nalgebra::Vector3;
use sycamore::prelude::*; use sycamore::prelude::*;
use web_sys::{console, wasm_bindgen::JsValue}; use web_sys::{console, wasm_bindgen::JsValue};
@ -882,6 +882,436 @@ fn load_irisawa_hexlet(assembly: &Assembly) {
assembly.insert_regulator(Rc::new(outer_moon_tangency)); assembly.insert_regulator(Rc::new(outer_moon_tangency));
} }
fn load_554a(assembly: &Assembly) {
// create the vertices
const COLOR_A: ElementColor = [0.75_f32, 0.00_f32, 0.75_f32];
const COLOR_B: ElementColor = [1.00_f32, 0.00_f32, 0.25_f32];
const COLOR_C: ElementColor = [0.75_f32, 0.50_f32, 0.00_f32];
const COLOR_D: ElementColor = [0.90_f32, 0.90_f32, 0.00_f32];
const COLOR_E: ElementColor = [0.25_f32, 0.75_f32, 0.00_f32];
const COLOR_F: ElementColor = [0.00_f32, 0.50_f32, 0.75_f32];
const COLOR_G: ElementColor = [0.25_f32, 0.00_f32, 1.00_f32];
let vertices = [
Point::new(
"a_NE".to_string(),
"A-NE".to_string(),
COLOR_A,
engine::point(0.5, 0.5, 0.0),
),
Point::new(
"a_NW".to_string(),
"A-NW".to_string(),
COLOR_A,
engine::point(-0.5, 0.5, 0.0),
),
Point::new(
"a_SW".to_string(),
"A-SW".to_string(),
COLOR_A,
engine::point(-0.5, -0.5, 0.0),
),
Point::new(
"a_SE".to_string(),
"A-SE".to_string(),
COLOR_A,
engine::point(0.5, -0.5, 0.0),
),
Point::new(
"b_NE".to_string(),
"B-NE".to_string(),
COLOR_B,
engine::point(0.7, 0.7, 0.9),
),
Point::new(
"b_NW".to_string(),
"B-NW".to_string(),
COLOR_B,
engine::point(-0.7, 0.7, 0.9),
),
Point::new(
"b_SW".to_string(),
"B-SW".to_string(),
COLOR_B,
engine::point(-0.7, -0.7, 0.9),
),
Point::new(
"b_SE".to_string(),
"B-SE".to_string(),
COLOR_B,
engine::point(0.7, -0.7, 0.9),
),
Point::new(
"c_N".to_string(),
"C-N".to_string(),
COLOR_C,
engine::point(0.0, 0.8, 1.4),
),
Point::new(
"c_W".to_string(),
"C-W".to_string(),
COLOR_C,
engine::point(-0.8, 0.0, 1.4),
),
Point::new(
"c_S".to_string(),
"C-S".to_string(),
COLOR_C,
engine::point(0.0, -0.8, 1.4),
),
Point::new(
"c_E".to_string(),
"C-E".to_string(),
COLOR_C,
engine::point(0.8, 0.0, 1.4),
),
Point::new(
"d_NE".to_string(),
"D-NE".to_string(),
COLOR_D,
engine::point(0.1, 0.1, 1.8),
),
Point::new(
"d_NW".to_string(),
"D-NW".to_string(),
COLOR_D,
engine::point(-0.1, 0.1, 1.8),
),
Point::new(
"d_SW".to_string(),
"D-SW".to_string(),
COLOR_D,
engine::point(-0.1, -0.1, 1.8),
),
Point::new(
"d_SE".to_string(),
"D-SE".to_string(),
COLOR_D,
engine::point(0.1, -0.1, 1.8),
),
Point::new(
"e_N".to_string(),
"E-N".to_string(),
COLOR_E,
engine::point(0.0, 0.7, 2.3),
),
Point::new(
"e_W".to_string(),
"E-W".to_string(),
COLOR_E,
engine::point(-0.7, 0.0, 2.3),
),
Point::new(
"e_S".to_string(),
"E-S".to_string(),
COLOR_E,
engine::point(0.0, -0.7, 2.3),
),
Point::new(
"e_E".to_string(),
"E-E".to_string(),
COLOR_E,
engine::point(0.7, 0.0, 2.3),
),
Point::new(
"f_NE".to_string(),
"F-NE".to_string(),
COLOR_F,
engine::point(0.2, 0.2, 2.7),
),
Point::new(
"f_NW".to_string(),
"F-NW".to_string(),
COLOR_F,
engine::point(-0.2, 0.2, 2.7),
),
Point::new(
"f_SW".to_string(),
"F-SW".to_string(),
COLOR_F,
engine::point(-0.2, -0.2, 2.7),
),
Point::new(
"f_SE".to_string(),
"F-SE".to_string(),
COLOR_F,
engine::point(0.2, -0.2, 2.7),
),
Point::new(
"g_NNE".to_string(),
"G-NNE".to_string(),
COLOR_G,
engine::point(0.5, 1.2, 3.0),
),
Point::new(
"g_NNW".to_string(),
"G-NNW".to_string(),
COLOR_G,
engine::point(-0.5, 1.2, 3.0),
),
Point::new(
"g_WNW".to_string(),
"G-WNW".to_string(),
COLOR_G,
engine::point(-1.2, 0.5, 3.0),
),
Point::new(
"g_WSW".to_string(),
"G-WSW".to_string(),
COLOR_G,
engine::point(-1.2, -0.5, 3.0),
),
Point::new(
"g_SSW".to_string(),
"G-SSW".to_string(),
COLOR_G,
engine::point(-0.5, -1.2, 3.0),
),
Point::new(
"g_SSE".to_string(),
"G-SSE".to_string(),
COLOR_G,
engine::point(0.5, -1.2, 3.0),
),
Point::new(
"g_ESE".to_string(),
"G-ESE".to_string(),
COLOR_G,
engine::point(1.2, -0.5, 3.0),
),
Point::new(
"g_ENE".to_string(),
"G-ENE".to_string(),
COLOR_G,
engine::point(1.2, 0.5, 3.0),
),
];
for vertex in vertices {
let _ = assembly.try_insert_element(vertex);
}
// fix the distances between adjacent vertices
let square_in_octagon = (2.0 + SQRT_2).sqrt();
let struts = [
(1.0, vec![
["a_NE", "a_NW"],
["a_NW", "a_SW"],
["a_SW", "a_SE"],
["a_SE", "a_NE"],
["a_NE", "b_NE"],
["a_NW", "b_NW"],
["a_SW", "b_SW"],
["a_SE", "b_SE"],
["b_NE", "c_N"],
["b_NW", "c_N"],
["b_NW", "c_W"],
["b_SW", "c_W"],
["b_SW", "c_S"],
["b_SE", "c_S"],
["b_SE", "c_E"],
["b_NE", "c_E"],
["c_N", "d_NE"],
["c_N", "d_NW"],
["c_W", "d_NW"],
["c_W", "d_SW"],
["c_S", "d_SW"],
["c_S", "d_SE"],
["c_E", "d_SE"],
["c_E", "d_NE"],
["d_NE", "e_N"],
["d_NW", "e_N"],
["d_NW", "e_W"],
["d_SW", "e_W"],
["d_SW", "e_S"],
["d_SE", "e_S"],
["d_SE", "e_E"],
["d_NE", "e_E"],
["c_N", "e_N"],
["c_W", "e_W"],
["c_S", "e_S"],
["c_E", "e_E"],
["e_N", "f_NE"],
["e_N", "f_NW"],
["e_W", "f_NW"],
["e_W", "f_SW"],
["e_S", "f_SW"],
["e_S", "f_SE"],
["e_E", "f_SE"],
["e_E", "f_NE"],
["d_NE", "f_NE"],
["d_NW", "f_NW"],
["d_SW", "f_SW"],
["d_SE", "f_SE"],
["f_NE", "g_ENE"],
["f_NE", "g_NNE"],
["f_NW", "g_NNW"],
["f_NW", "g_WNW"],
["f_SW", "g_WSW"],
["f_SW", "g_SSW"],
["f_SE", "g_SSE"],
["f_SE", "g_ESE"],
["e_N", "g_NNE"],
["e_N", "g_NNW"],
["e_W", "g_WNW"],
["e_W", "g_WSW"],
["e_S", "g_SSW"],
["e_S", "g_SSE"],
["e_E", "g_ESE"],
["e_E", "g_ENE"],
["g_NNE", "g_NNW"],
["g_NNW", "g_WNW"],
["g_WNW", "g_WSW"],
["g_WSW", "g_SSW"],
["g_SSW", "g_SSE"],
["g_SSE", "g_ESE"],
["g_ESE", "g_ENE"],
["g_ENE", "g_NNE"],
]),
(SQRT_2, vec![
["a_NE", "a_SW"],
["a_NW", "a_SE"],
["b_NE", "d_NE"],
["b_NW", "d_NW"],
["b_SW", "d_SW"],
["b_SE", "d_SE"],
]),
(0.5*(1.0 + 5.0_f64.sqrt()), vec![
["a_NE", "c_N"],
["a_NW", "c_N"],
["a_NW", "c_W"],
["a_SW", "c_W"],
["a_SW", "c_S"],
["a_SE", "c_S"],
["a_SE", "c_E"],
["a_NE", "c_E"],
]),
(square_in_octagon, vec![
["g_NNE", "g_WNW"],
["g_WNW", "g_SSW"],
["g_SSW", "g_ESE"],
["g_ESE", "g_NNE"],
]),
(SQRT_2 * square_in_octagon, vec![
["g_NNE", "g_SSW"],
]),
];
for (length, vertex_pairs) in struts {
let inv_dist = Some(-0.5 * length * length);
for pair in vertex_pairs {
let adjacent_vertices = pair.map(
|id| assembly.elements_by_id.with_untracked(
|elts_by_id| elts_by_id[id].clone()
)
);
let distance = InversiveDistanceRegulator::new(adjacent_vertices);
distance.set_point.set(SpecifiedValue::from(inv_dist));
assembly.insert_regulator(Rc::new(distance));
}
}
// create the faces
const COLOR_FACE: ElementColor = [0.75_f32, 0.75_f32, 0.75_f32];
let faces = [
Sphere::new(
"f_a".to_string(),
"Face A".to_string(),
COLOR_FACE,
engine::sphere_with_offset(0.0, 0.0, -1.0, 0.0, 0.0),
),
Sphere::new(
"f_abc_N".to_string(),
"Face ABC-N".to_string(),
COLOR_FACE,
engine::sphere_with_offset(0.0, 1.0, 0.0, 0.5, 0.0),
),
Sphere::new(
"f_abc_W".to_string(),
"Face ABC-W".to_string(),
COLOR_FACE,
engine::sphere_with_offset(-1.0, 0.0, 0.0, 0.5, 0.0),
),
Sphere::new(
"f_abc_S".to_string(),
"Face ABC-S".to_string(),
COLOR_FACE,
engine::sphere_with_offset(0.0, -1.0, 0.0, 0.5, 0.0),
),
Sphere::new(
"f_abc_E".to_string(),
"Face ABC-E".to_string(),
COLOR_FACE,
engine::sphere_with_offset(1.0, 0.0, 0.0, 0.5, 0.0),
),
Sphere::new(
"f_bcd_NE".to_string(),
"Face BCD-NE".to_string(),
COLOR_FACE,
engine::sphere_with_offset(FRAC_1_SQRT_2, FRAC_1_SQRT_2, 0.0, FRAC_1_SQRT_2, 0.0),
),
Sphere::new(
"f_bcd_NW".to_string(),
"Face BCD-NW".to_string(),
COLOR_FACE,
engine::sphere_with_offset(-FRAC_1_SQRT_2, FRAC_1_SQRT_2, 0.0, FRAC_1_SQRT_2, 0.0),
),
Sphere::new(
"f_bcd_SW".to_string(),
"Face BCD-SW".to_string(),
COLOR_FACE,
engine::sphere_with_offset(-FRAC_1_SQRT_2, -FRAC_1_SQRT_2, 0.0, FRAC_1_SQRT_2, 0.0),
),
Sphere::new(
"f_bcd_SE".to_string(),
"Face BCD-SE".to_string(),
COLOR_FACE,
engine::sphere_with_offset(FRAC_1_SQRT_2, -FRAC_1_SQRT_2, 0.0, FRAC_1_SQRT_2, 0.0),
),
Sphere::new(
"f_g".to_string(),
"Face G".to_string(),
COLOR_FACE,
engine::sphere_with_offset(0.0, 0.0, 1.0, 3.0, 0.0),
),
];
for face in faces {
face.ghost().set(true);
let _ = assembly.try_insert_element(face);
}
// make the faces planar and make them pass through their vertices
let face_incidences = [
("f_a", vec!["a_NE", "a_NW", "a_SW", "a_SE"]),
("f_abc_N", vec!["a_NE", "a_NW", "b_NE", "b_NW", "c_N"]),
("f_abc_W", vec!["a_NW", "a_SW", "b_NW", "b_SW", "c_W"]),
("f_abc_S", vec!["a_SW", "a_SE", "b_SW", "b_SE", "c_S"]),
("f_abc_E", vec!["a_SE", "a_NE", "b_SE", "b_NE", "c_E"]),
("f_bcd_NE", vec!["b_NE", "c_N", "c_E", "d_NE"]),
("f_bcd_NW", vec!["b_NW", "c_N", "c_W", "d_NW"]),
("f_bcd_SW", vec!["b_SW", "c_S", "c_W", "d_SW"]),
("f_bcd_SE", vec!["b_SE", "c_S", "c_E", "d_SE"]),
("f_g", vec!["g_NNE", "g_NNW", "g_WNW", "g_WSW", "g_SSW", "g_SSE", "g_ESE", "g_ENE"]),
];
for (face_id, vertex_ids) in face_incidences {
// make the face planar
let face = assembly.elements_by_id.with_untracked(
|elts_by_id| elts_by_id[face_id].clone()
);
let curvature_regulator = face.regulators().with_untracked(
|regs| regs.first().unwrap().clone()
);
curvature_regulator.set_point().set(SpecifiedValue::from(Some(0.0)));
// make the face pass through its vertices
for v_id in vertex_ids {
let vertex = assembly.elements_by_id.with_untracked(
|elts_by_id| elts_by_id[v_id].clone()
);
let incidence = InversiveDistanceRegulator::new([face.clone(), vertex]);
incidence.set_point.set(SpecifiedValue::from(Some(0.0)));
assembly.insert_regulator(Rc::new(incidence));
}
}
}
// --- chooser --- // --- chooser ---
/* DEBUG */ /* DEBUG */
@ -918,6 +1348,7 @@ pub fn TestAssemblyChooser() -> View {
"off-center" => load_off_center(assembly), "off-center" => load_off_center(assembly),
"radius-ratio" => load_radius_ratio(assembly), "radius-ratio" => load_radius_ratio(assembly),
"irisawa-hexlet" => load_irisawa_hexlet(assembly), "irisawa-hexlet" => load_irisawa_hexlet(assembly),
"554a" => load_554a(assembly),
_ => (), _ => (),
}; };
}); });
@ -935,6 +1366,7 @@ pub fn TestAssemblyChooser() -> View {
option(value = "off-center") { "Off-center" } option(value = "off-center") { "Off-center" }
option(value = "radius-ratio") { "Radius ratio" } option(value = "radius-ratio") { "Radius ratio" }
option(value = "irisawa-hexlet") { "Irisawa hexlet" } option(value = "irisawa-hexlet") { "Irisawa hexlet" }
option(value = "554a") { "5-5-4 near miss A" }
option(value = "empty") { "Empty" } option(value = "empty") { "Empty" }
} }
} }