use glam::Vec3;
use super::StandardGemCuts;
use crate::geometry::plane::GpuFacetPlane;
impl StandardGemCuts {
#[must_use]
pub fn emerald_cut() -> Vec<GpuFacetPlane> {
const TABLE_Y: f32 = 0.30; const GIRDLE_HALF_BAND: f32 = 0.03; const CROWN_CREASE_Y: f32 = 0.15; const PAVILION_CREASE_MAG: f32 = 0.35; const GIRDLE_R_Z: f32 = 0.80;
const GIRDLE_R_X: f32 = 1.10;
const GIRDLE_R_DIAG: f32 = 1.00;
const PAVILION_KEEL_Y: f32 = -0.86;
let diag = std::f32::consts::FRAC_1_SQRT_2;
let mut planes = Vec::new();
planes.push(GpuFacetPlane::new(Vec3::new(0.0, 1.0, 0.0), -TABLE_Y));
let a1 = 35.0f32.to_radians(); let a2 = 45.0f32.to_radians(); push_crown_tiers(
&mut planes,
a1,
a2,
GIRDLE_R_Z,
GIRDLE_R_X,
GIRDLE_HALF_BAND,
CROWN_CREASE_Y,
);
let ac = 40.0f32.to_radians();
push_corner_facets(&mut planes, ac, GIRDLE_R_DIAG, GIRDLE_HALF_BAND, diag, 1.0);
push_girdle_facets(&mut planes, GIRDLE_R_Z, GIRDLE_R_X, GIRDLE_R_DIAG, diag);
let p1 = 53.0f32.to_radians(); let p2 = 43.0f32.to_radians(); push_pavilion_tiers(
&mut planes,
p1,
p2,
GIRDLE_R_Z,
GIRDLE_R_X,
GIRDLE_HALF_BAND,
PAVILION_CREASE_MAG,
);
let pc = 48.0f32.to_radians();
push_corner_facets(&mut planes, pc, GIRDLE_R_DIAG, GIRDLE_HALF_BAND, diag, -1.0);
planes.push(GpuFacetPlane::new(
Vec3::new(0.0, -1.0, 0.0),
PAVILION_KEEL_Y,
));
planes
}
}
fn tier_d_at_girdle(angle: f32, r: f32, half_band: f32) -> f32 {
-angle.sin().mul_add(r, angle.cos() * half_band)
}
fn tier_d_at_crease(
girdle_angle: f32,
crease_angle: f32,
r: f32,
crease_mag: f32,
half_band: f32,
) -> f32 {
let z_c = r - girdle_angle.cos() * (crease_mag - half_band) / girdle_angle.sin();
-crease_angle
.sin()
.mul_add(z_c, crease_angle.cos() * crease_mag)
}
fn corner_d(angle: f32, r_diag: f32, half_band: f32) -> f32 {
-angle.cos().mul_add(half_band, angle.sin() * r_diag)
}
fn push_crown_tiers(
planes: &mut Vec<GpuFacetPlane>,
a1: f32,
a2: f32,
r_z: f32,
r_x: f32,
half_band: f32,
crease_y: f32,
) {
let d_a1_z = tier_d_at_crease(a2, a1, r_z, crease_y, half_band);
let d_a1_x = tier_d_at_crease(a2, a1, r_x, crease_y, half_band);
let d_a2_z = tier_d_at_girdle(a2, r_z, half_band);
let d_a2_x = tier_d_at_girdle(a2, r_x, half_band);
planes.push(GpuFacetPlane::new(
Vec3::new(0.0, a1.cos(), a1.sin()),
d_a1_z,
));
planes.push(GpuFacetPlane::new(
Vec3::new(0.0, a1.cos(), -a1.sin()),
d_a1_z,
));
planes.push(GpuFacetPlane::new(
Vec3::new(a1.sin(), a1.cos(), 0.0),
d_a1_x,
));
planes.push(GpuFacetPlane::new(
Vec3::new(-a1.sin(), a1.cos(), 0.0),
d_a1_x,
));
planes.push(GpuFacetPlane::new(
Vec3::new(0.0, a2.cos(), a2.sin()),
d_a2_z,
));
planes.push(GpuFacetPlane::new(
Vec3::new(0.0, a2.cos(), -a2.sin()),
d_a2_z,
));
planes.push(GpuFacetPlane::new(
Vec3::new(a2.sin(), a2.cos(), 0.0),
d_a2_x,
));
planes.push(GpuFacetPlane::new(
Vec3::new(-a2.sin(), a2.cos(), 0.0),
d_a2_x,
));
}
fn push_pavilion_tiers(
planes: &mut Vec<GpuFacetPlane>,
p1: f32,
p2: f32,
r_z: f32,
r_x: f32,
half_band: f32,
crease_mag: f32,
) {
let d_p1_z = tier_d_at_girdle(p1, r_z, half_band);
let d_p1_x = tier_d_at_girdle(p1, r_x, half_band);
let d_p2_z = tier_d_at_crease(p1, p2, r_z, crease_mag, half_band);
let d_p2_x = tier_d_at_crease(p1, p2, r_x, crease_mag, half_band);
planes.push(GpuFacetPlane::new(
Vec3::new(0.0, -p1.cos(), p1.sin()),
d_p1_z,
));
planes.push(GpuFacetPlane::new(
Vec3::new(0.0, -p1.cos(), -p1.sin()),
d_p1_z,
));
planes.push(GpuFacetPlane::new(
Vec3::new(p1.sin(), -p1.cos(), 0.0),
d_p1_x,
));
planes.push(GpuFacetPlane::new(
Vec3::new(-p1.sin(), -p1.cos(), 0.0),
d_p1_x,
));
planes.push(GpuFacetPlane::new(
Vec3::new(0.0, -p2.cos(), p2.sin()),
d_p2_z,
));
planes.push(GpuFacetPlane::new(
Vec3::new(0.0, -p2.cos(), -p2.sin()),
d_p2_z,
));
planes.push(GpuFacetPlane::new(
Vec3::new(p2.sin(), -p2.cos(), 0.0),
d_p2_x,
));
planes.push(GpuFacetPlane::new(
Vec3::new(-p2.sin(), -p2.cos(), 0.0),
d_p2_x,
));
}
fn push_corner_facets(
planes: &mut Vec<GpuFacetPlane>,
angle: f32,
r_diag: f32,
half_band: f32,
diag: f32,
y_sign: f32,
) {
let d = corner_d(angle, r_diag, half_band);
let y = y_sign * angle.cos();
let s = angle.sin() * diag;
planes.push(GpuFacetPlane::new(Vec3::new(s, y, s), d));
planes.push(GpuFacetPlane::new(Vec3::new(-s, y, s), d));
planes.push(GpuFacetPlane::new(Vec3::new(s, y, -s), d));
planes.push(GpuFacetPlane::new(Vec3::new(-s, y, -s), d));
}
fn push_girdle_facets(planes: &mut Vec<GpuFacetPlane>, r_z: f32, r_x: f32, r_diag: f32, diag: f32) {
planes.push(GpuFacetPlane::new(Vec3::new(0.0, 0.0, 1.0), -r_z));
planes.push(GpuFacetPlane::new(Vec3::new(0.0, 0.0, -1.0), -r_z));
planes.push(GpuFacetPlane::new(Vec3::new(1.0, 0.0, 0.0), -r_x));
planes.push(GpuFacetPlane::new(Vec3::new(-1.0, 0.0, 0.0), -r_x));
planes.push(GpuFacetPlane::new(Vec3::new(diag, 0.0, diag), -r_diag));
planes.push(GpuFacetPlane::new(Vec3::new(-diag, 0.0, diag), -r_diag));
planes.push(GpuFacetPlane::new(Vec3::new(diag, 0.0, -diag), -r_diag));
planes.push(GpuFacetPlane::new(Vec3::new(-diag, 0.0, -diag), -r_diag));
}