cubesim 0.0.7

Rubik's Cube simulation and solving library.
Documentation
use cgmath::{Basis3, Deg, Rotation3};

use crate::generic_cube::{Move, MoveVariant, CubeSize};
use crate::generic_cube::Move::*;
use crate::generic_cube::MoveVariant::*;

use super::sticker::Sticker;

pub struct GeometricMove {
    axis: Axis,
    angle: f64,
    pub predicate: Box<dyn Fn(&Sticker) -> bool>
}

impl GeometricMove {
    pub fn get_rotation_matrix(&self) -> Basis3<f64> {
        match self.axis {
            Axis::X => Basis3::from_angle_x(Deg(-self.angle)),
            Axis::Y => Basis3::from_angle_y(Deg(-self.angle)),
            Axis::Z => Basis3::from_angle_z(Deg(-self.angle))
        }
    }

    pub fn from(mv: Move) -> Self {
        match (mv, 1) {
            (U(variant), n) | (Uw(n, variant), _) => modify_move(u_move(n), variant),
            (R(variant), n) | (Rw(n, variant), _) => modify_move(r_move(n), variant),
            (F(variant), n) | (Fw(n, variant), _) => modify_move(f_move(n), variant),
            (L(variant), n) | (Lw(n, variant), _) => modify_move(l_move(n), variant),
            (D(variant), n) | (Dw(n, variant), _) => modify_move(d_move(n), variant),
            (B(variant), n) | (Bw(n, variant), _) => modify_move(b_move(n), variant),
            (X(variant), _) => modify_move(x_move(), variant),
            (Y(variant), _) => modify_move(y_move(), variant),
            (Z(variant), _) => modify_move(z_move(), variant),
        }
    }
}

#[derive(Copy, Clone)]
pub enum Axis {
    X, Y, Z
}

fn modify_move(mv: GeometricMove, variant: MoveVariant) -> GeometricMove {
    match variant {
        Standard => mv,
        Double => GeometricMove { angle: 2.0 * mv.angle, ..mv },
        Inverse => GeometricMove { angle: -mv.angle, ..mv }
    }
}

fn u_move(n: CubeSize) -> GeometricMove {
    GeometricMove { 
        predicate: Box::new(move |s| s.current.y >= s.size - (n * 2)),
        ..y_move()
    }
}
fn d_move(n: CubeSize) -> GeometricMove { 
    modify_move(GeometricMove { 
        predicate: Box::new(move |s| s.current.y <= -s.size + (n * 2)),
        ..y_move()
    }, Inverse)
}
fn y_move() -> GeometricMove { 
    GeometricMove { axis: Axis::Y, angle: 90.0, predicate: Box::new(|_| true) }
}

fn l_move(n: CubeSize) -> GeometricMove { 
    modify_move(GeometricMove { 
        predicate: Box::new(move |s| s.current.x <= -s.size + (n * 2)),
        ..x_move() 
    }, Inverse)
}
fn r_move(n: CubeSize) -> GeometricMove {
    GeometricMove { 
        predicate: Box::new(move |s| s.current.x >= s.size - (n * 2)),
        ..x_move()
    }
}
fn x_move() -> GeometricMove { 
    GeometricMove { axis: Axis::X, angle: 90.0, predicate: Box::new(|_| true) }
}

fn f_move(n: CubeSize) -> GeometricMove { 
    GeometricMove { 
        predicate: Box::new(move |s| s.current.z >= s.size - (n * 2)),
        ..z_move()
    }
}
fn b_move(n: CubeSize) -> GeometricMove { 
    modify_move(GeometricMove { 
        predicate: Box::new(move |s| s.current.z <= -s.size + (n * 2)),
        ..z_move()
    }, Inverse)
}
fn z_move() -> GeometricMove { 
    GeometricMove { axis: Axis::Z, angle: 90.0, predicate: Box::new(|_| true) }
}