use crate::*;
use num_traits::float::FloatConst;
impl Polyhedron {
pub fn tetrahedron() -> Self {
let c0 = 1.0;
Self {
positions: vec![
Point::new(c0, c0, c0),
Point::new(c0, -c0, -c0),
Point::new(-c0, c0, -c0),
Point::new(-c0, -c0, c0),
],
face_index: vec![
vec![2, 1, 0],
vec![3, 2, 0],
vec![1, 3, 0],
vec![2, 3, 1],
],
face_set_index: vec![(0..4).collect()],
name: String::from("T"),
}
}
pub fn hexahedron() -> Self {
let c0 = 1.0;
Self {
positions: vec![
Point::new(c0, c0, c0),
Point::new(c0, c0, -c0),
Point::new(c0, -c0, c0),
Point::new(c0, -c0, -c0),
Point::new(-c0, c0, c0),
Point::new(-c0, c0, -c0),
Point::new(-c0, -c0, c0),
Point::new(-c0, -c0, -c0),
],
face_index: vec![
vec![4, 5, 1, 0],
vec![2, 6, 4, 0],
vec![1, 3, 2, 0],
vec![6, 2, 3, 7],
vec![5, 4, 6, 7],
vec![3, 1, 5, 7],
],
face_set_index: vec![(0..6).collect()],
name: String::from("C"),
}
}
#[inline]
pub fn cube() -> Self {
Self::hexahedron()
}
pub fn octahedron() -> Self {
let c0 = 0.707_106_77;
Self {
positions: vec![
Point::new(0.0, 0.0, c0),
Point::new(0.0, 0.0, -c0),
Point::new(c0, 0.0, 0.0),
Point::new(-c0, 0.0, 0.0),
Point::new(0.0, c0, 0.0),
Point::new(0.0, -c0, 0.0),
],
face_index: vec![
vec![4, 2, 0],
vec![3, 4, 0],
vec![5, 3, 0],
vec![2, 5, 0],
vec![5, 2, 1],
vec![3, 5, 1],
vec![4, 3, 1],
vec![2, 4, 1],
],
face_set_index: vec![(0..8).collect()],
name: String::from("O"),
}
}
pub fn dodecahedron() -> Self {
let c0 = 0.809_017;
let c1 = 1.309_017;
Self {
positions: vec![
Point::new(0.0, 0.5, c1),
Point::new(0.0, 0.5, -c1),
Point::new(0.0, -0.5, c1),
Point::new(0.0, -0.5, -c1),
Point::new(c1, 0.0, 0.5),
Point::new(c1, 0.0, -0.5),
Point::new(-c1, 0.0, 0.5),
Point::new(-c1, 0.0, -0.5),
Point::new(0.5, c1, 0.0),
Point::new(0.5, -c1, 0.0),
Point::new(-0.5, c1, 0.0),
Point::new(-0.5, -c1, 0.0),
Point::new(c0, c0, c0),
Point::new(c0, c0, -c0),
Point::new(c0, -c0, c0),
Point::new(c0, -c0, -c0),
Point::new(-c0, c0, c0),
Point::new(-c0, c0, -c0),
Point::new(-c0, -c0, c0),
Point::new(-c0, -c0, -c0),
],
face_index: vec![
vec![12, 4, 14, 2, 0],
vec![16, 10, 8, 12, 0],
vec![2, 18, 6, 16, 0],
vec![17, 10, 16, 6, 7],
vec![19, 3, 1, 17, 7],
vec![6, 18, 11, 19, 7],
vec![15, 3, 19, 11, 9],
vec![14, 4, 5, 15, 9],
vec![11, 18, 2, 14, 9],
vec![8, 10, 17, 1, 13],
vec![5, 4, 12, 8, 13],
vec![1, 3, 15, 5, 13],
],
face_set_index: vec![(0..12).collect()],
name: String::from("D"),
}
}
pub fn icosahedron() -> Self {
let c0 = 0.809_017;
Self {
positions: vec![
Point::new(0.5, 0.0, c0),
Point::new(0.5, 0.0, -c0),
Point::new(-0.5, 0.0, c0),
Point::new(-0.5, 0.0, -c0),
Point::new(c0, 0.5, 0.0),
Point::new(c0, -0.5, 0.0),
Point::new(-c0, 0.5, 0.0),
Point::new(-c0, -0.5, 0.0),
Point::new(0.0, c0, 0.5),
Point::new(0.0, c0, -0.5),
Point::new(0.0, -c0, 0.5),
Point::new(0.0, -c0, -0.5),
],
face_index: vec![
vec![10, 2, 0],
vec![5, 10, 0],
vec![4, 5, 0],
vec![8, 4, 0],
vec![2, 8, 0],
vec![6, 8, 2],
vec![7, 6, 2],
vec![10, 7, 2],
vec![11, 7, 10],
vec![5, 11, 10],
vec![1, 11, 5],
vec![4, 1, 5],
vec![9, 1, 4],
vec![8, 9, 4],
vec![6, 9, 8],
vec![3, 9, 6],
vec![7, 3, 6],
vec![11, 3, 7],
vec![1, 3, 11],
vec![9, 3, 1],
],
face_set_index: vec![(0..20).collect()],
name: String::from("I"),
}
}
#[inline]
fn protoprism(n: Option<usize>, anti: bool) -> Self {
let n = n.unwrap_or(3);
let theta = f32::TAU() / n as f32;
let twist = if anti { theta / 2.0 } else { 0.0 };
let h = (theta * 0.5).sin();
let mut face_index = vec![
(0..n).map(|i| i as VertexKey).collect::<Vec<_>>(),
(n..2 * n).rev().map(|i| i as VertexKey).collect::<Vec<_>>(),
];
if anti {
face_index.extend(
(0..n)
.map(|i| {
vec![
i as VertexKey,
(i + n) as VertexKey,
((i + 1) % n) as VertexKey,
]
})
.chain((0..n).map(|i| {
vec![
(i + n) as VertexKey,
((i + 1) % n + n) as VertexKey,
((i + 1) % n) as VertexKey,
]
})),
);
} else {
face_index.extend((0..n).map(|i| {
vec![
i as VertexKey,
(i + n) as VertexKey,
((i + 1) % n + n) as VertexKey,
((i + 1) % n) as VertexKey,
]
}));
};
Self {
name: format!("{}{}", if anti { "A" } else { "P" }, n),
positions: (0..n)
.map(move |i| {
Point::new(
(i as f32 * theta).cos() as _,
h,
(i as f32 * theta).sin() as _,
)
})
.chain((0..n).map(move |i| {
Point::new(
(twist + i as f32 * theta).cos() as _,
-h,
(twist + i as f32 * theta).sin() as _,
)
}))
.collect(),
face_index,
face_set_index: Vec::new(),
}
}
pub fn prism(n: Option<usize>) -> Self {
Self::protoprism(n, false)
}
pub fn antiprism(n: Option<usize>) -> Self {
Self::protoprism(n, true)
}
}