use std::fmt;
use std::str::FromStr;
use super::error::{Error, Result};
#[derive(Debug, Clone, Default)]
pub struct BeamLattice {
pub min_length: f64,
pub radius: f64,
pub ball_mode: BallMode,
pub ball_radius: Option<f64>,
pub clipping_mode: ClippingMode,
pub clipping_mesh: Option<u32>,
pub representation_mesh: Option<u32>,
pub pid: Option<u32>,
pub pindex: Option<u32>,
pub cap: CapMode,
pub beams: Beams,
pub balls: Balls,
pub beam_sets: BeamSets,
}
impl BeamLattice {
pub fn new(minlength: f64, radius: f64) -> Self {
Self {
min_length: minlength,
radius,
ball_mode: BallMode::None,
ball_radius: None,
clipping_mode: ClippingMode::None,
clipping_mesh: None,
representation_mesh: None,
pid: None,
pindex: None,
cap: CapMode::Sphere,
beams: Beams::default(),
balls: Balls::default(),
beam_sets: BeamSets::default(),
}
}
pub fn add_beam(&mut self, beam: Beam) -> u32 {
let index = self.beams.beams.len() as u32;
self.beams.beams.push(beam);
index
}
pub fn add_ball(&mut self, ball: Ball) -> u32 {
let index = self.balls.balls.len() as u32;
self.balls.balls.push(ball);
index
}
pub fn add_beamset(&mut self, beamset: BeamSet) -> u32 {
let index = self.beam_sets.beam_sets.len() as u32;
self.beam_sets.beam_sets.push(beamset);
index
}
pub fn set_ball_mode(&mut self, ballmode: BallMode) -> &mut Self {
self.ball_mode = ballmode;
self
}
pub fn set_ball_radius(&mut self, ballradius: f64) -> &mut Self {
self.ball_radius = Some(ballradius);
self
}
pub fn set_clipping_mode(&mut self, clippingmode: ClippingMode) -> &mut Self {
self.clipping_mode = clippingmode;
self
}
pub fn set_clipping_mesh(&mut self, clippingmesh: u32) -> &mut Self {
self.clipping_mesh = Some(clippingmesh);
self
}
pub fn set_representation_mesh(&mut self, representationmesh: u32) -> &mut Self {
self.representation_mesh = Some(representationmesh);
self
}
pub fn set_material(&mut self, pid: u32, pindex: u32) -> &mut Self {
self.pid = Some(pid);
self.pindex = Some(pindex);
self
}
pub fn set_cap_mode(&mut self, cap: CapMode) -> &mut Self {
self.cap = cap;
self
}
pub fn beam_count(&self) -> usize {
self.beams.beams.len()
}
pub fn ball_count(&self) -> usize {
self.balls.balls.len()
}
pub fn beam_set_count(&self) -> usize {
self.beam_sets.beam_sets.len()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum ClippingMode {
#[default]
None,
Inside,
Outside,
}
impl fmt::Display for ClippingMode {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ClippingMode::None => write!(f, "none"),
ClippingMode::Inside => write!(f, "inside"),
ClippingMode::Outside => write!(f, "outside"),
}
}
}
impl FromStr for ClippingMode {
type Err = Error;
fn from_str(s: &str) -> Result<Self> {
match s.to_lowercase().as_str() {
"none" => Ok(ClippingMode::None),
"inside" => Ok(ClippingMode::Inside),
"outside" => Ok(ClippingMode::Outside),
_ => Err(Error::InvalidAttribute {
name: "clippingmode".to_string(),
message: format!("unknown clipping mode: {}", s),
}),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum CapMode {
Hemisphere,
#[default]
Sphere,
Butt,
}
impl fmt::Display for CapMode {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
CapMode::Hemisphere => write!(f, "hemisphere"),
CapMode::Sphere => write!(f, "sphere"),
CapMode::Butt => write!(f, "butt"),
}
}
}
impl FromStr for CapMode {
type Err = Error;
fn from_str(s: &str) -> Result<Self> {
match s.to_lowercase().as_str() {
"hemisphere" => Ok(CapMode::Hemisphere),
"sphere" => Ok(CapMode::Sphere),
"butt" => Ok(CapMode::Butt),
_ => Err(Error::InvalidAttribute {
name: "capmode".to_string(),
message: format!("unknown cap mode: {}", s),
}),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum BallMode {
#[default]
None,
Mixed,
All,
}
impl fmt::Display for BallMode {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
BallMode::None => write!(f, "none"),
BallMode::Mixed => write!(f, "mixed"),
BallMode::All => write!(f, "all"),
}
}
}
impl FromStr for BallMode {
type Err = Error;
fn from_str(s: &str) -> Result<Self> {
match s.to_lowercase().as_str() {
"none" => Ok(BallMode::None),
"mixed" => Ok(BallMode::Mixed),
"all" => Ok(BallMode::All),
_ => Err(Error::InvalidAttribute {
name: "ballmode".to_string(),
message: format!("unknown ball mode: {}", s),
}),
}
}
}
#[derive(Debug, Clone, PartialEq, Default)]
pub struct Beams {
pub beams: Vec<Beam>,
}
#[derive(Debug, Clone, PartialEq, Default)]
pub struct Beam {
pub v1: u32,
pub v2: u32,
pub r1: Option<f64>,
pub r2: Option<f64>,
pub p1: Option<u32>,
pub p2: Option<u32>,
pub pid: Option<u32>,
pub cap1: Option<CapMode>,
pub cap2: Option<CapMode>,
}
impl Beam {
pub fn new(v1: u32, v2: u32) -> Self {
Self {
v1,
v2,
r1: None,
r2: None,
p1: None,
p2: None,
pid: None,
cap1: None,
cap2: None,
}
}
pub fn with_radius(v1: u32, v2: u32, r1: f64, r2: f64) -> Self {
Self {
v1,
v2,
r1: Some(r1),
r2: Some(r2),
p1: None,
p2: None,
pid: None,
cap1: None,
cap2: None,
}
}
pub fn with_property(mut self, pid: u32, pindex: u32) -> Self {
self.pid = Some(pid);
self.p1 = Some(pindex);
self.p2 = Some(pindex);
self
}
}
#[derive(Debug, Clone, PartialEq, Default)]
pub struct Balls {
pub balls: Vec<Ball>,
}
#[derive(Debug, Clone, PartialEq, Default)]
pub struct Ball {
pub vindex: u32,
pub r: Option<f64>,
pub p: Option<u32>,
pub pid: Option<u32>,
}
impl Ball {
pub fn new(vindex: u32) -> Self {
Self {
vindex,
r: None,
p: None,
pid: None,
}
}
pub fn with_radius(vindex: u32, r: f64) -> Self {
Self {
vindex,
r: Some(r),
p: None,
pid: None,
}
}
pub fn with_property(mut self, pid: u32, pindex: u32) -> Self {
self.pid = Some(pid);
self.p = Some(pindex);
self
}
}
#[derive(Debug, Clone, PartialEq, Default)]
pub struct BeamRef {
pub index: u32,
}
impl BeamRef {
pub fn new(index: u32) -> Self {
Self { index }
}
}
#[derive(Debug, Clone, PartialEq, Default)]
pub struct BallRef {
pub index: u32,
}
impl BallRef {
pub fn new(index: u32) -> Self {
Self { index }
}
}
#[derive(Debug, Clone, PartialEq, Default)]
pub struct BeamSets {
pub beam_sets: Vec<BeamSet>,
}
#[derive(Debug, Clone, PartialEq, Default)]
pub struct BeamSet {
pub name: Option<String>,
pub identifier: Option<String>,
pub refs: Vec<BeamRef>,
pub ball_refs: Vec<BallRef>,
}
impl BeamSet {
pub fn new() -> Self {
Self::default()
}
pub fn with_name(name: impl Into<String>) -> Self {
Self {
name: Some(name.into()),
identifier: None,
refs: Vec::new(),
ball_refs: Vec::new(),
}
}
pub fn add_beam_ref(&mut self, index: u32) {
self.refs.push(BeamRef::new(index));
}
pub fn add_ball_ref(&mut self, index: u32) {
self.ball_refs.push(BallRef::new(index));
}
}