ak_vis/visuals/
convert.rs

1use crate::{AtomIdentity, AtomVisual, AxisVisual, CellVisual, ColorScheme, DEFAULT_ATOM_MATERIAL};
2use ak_core::{PERIODIC_TABLE, StructureView};
3use bevy::math::Vec3;
4use bevy::prelude::*;
5
6pub fn structure_vec3_to_world(vector: Vec3) -> Vec3 {
7    // Rotate structure-space coordinates so chemistry-style z-up becomes Bevy-world y-up.
8    Vec3::new(vector.x, vector.z, -vector.y)
9}
10
11pub fn structure_position_to_world(position: [f64; 3]) -> Vec3 {
12    structure_vec3_to_world(Vec3::new(
13        position[0] as f32,
14        position[1] as f32,
15        position[2] as f32,
16    ))
17}
18
19pub fn convert_structure<C: ColorScheme>(view: &StructureView, scheme: &C) -> Vec<AtomVisual> {
20    let mut visuals: Vec<AtomVisual> = Vec::with_capacity(view.len());
21    for i in 0..view.positions.len() {
22        let radius: f32 = 0.9 * PERIODIC_TABLE.get(view.numbers[i]).covalent_radius as f32;
23        let color = scheme.color(view, i);
24        let atom_visual = AtomVisual {
25            atom_identity: AtomIdentity {
26                atom_index: i,
27                image_offset: [0, 0, 0],
28            },
29            position: structure_position_to_world(view.positions[i]).to_array(),
30            color,
31            material: DEFAULT_ATOM_MATERIAL,
32            radius,
33        };
34        visuals.push(atom_visual);
35    }
36    visuals
37}
38
39pub fn convert_cell(view: &StructureView, cell_color: Color) -> Vec<CellVisual> {
40    let mut visuals: Vec<CellVisual> = Vec::new();
41
42    let a = structure_vec3_to_world(Vec3::from_slice(view.cell.a().cast::<f32>().as_slice()));
43    let b = structure_vec3_to_world(Vec3::from_slice(view.cell.b().cast::<f32>().as_slice()));
44    let c = structure_vec3_to_world(Vec3::from_slice(view.cell.c().cast::<f32>().as_slice()));
45    let origin = Vec3::ZERO;
46
47    let edges = [
48        (origin, a),
49        (a, a + b),
50        (a + b, b),
51        (b, origin),
52        (origin, c),
53        (c, c + b),
54        (c + b, b),
55        (c + b, c + b + a),
56        (c + b + a, b + a),
57        (c + b + a, c + a),
58        (c + a, c),
59        (c + a, a),
60    ];
61
62    for edge in edges {
63        let visual = CellVisual {
64            corner_1: edge.0,
65            corner_2: edge.1,
66            color: cell_color,
67        };
68        visuals.push(visual);
69    }
70
71    visuals
72}
73
74pub fn convert_axis(view: &StructureView) -> Vec<AxisVisual> {
75    let mut visuals: Vec<AxisVisual> = Vec::new();
76
77    let a = structure_vec3_to_world(Vec3::from_slice(view.cell.a().cast::<f32>().as_slice()));
78    let b = structure_vec3_to_world(Vec3::from_slice(view.cell.b().cast::<f32>().as_slice()));
79    let c = structure_vec3_to_world(Vec3::from_slice(view.cell.c().cast::<f32>().as_slice()));
80
81    let a_unit = a / a.length();
82    let b_unit = b / b.length();
83    let c_unit = c / c.length();
84
85    visuals.push(AxisVisual {
86        direction: a_unit,
87        color: Color::srgb_u8(255, 0, 0),
88        length: 1.0,
89    });
90    visuals.push(AxisVisual {
91        direction: b_unit,
92        color: Color::srgb_u8(0, 255, 0),
93        length: 1.0,
94    });
95    visuals.push(AxisVisual {
96        direction: c_unit,
97        color: Color::srgb_u8(0, 0, 255),
98        length: 1.0,
99    });
100    visuals
101}