use std::fmt;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Default)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum LineWeight {
#[default]
ByLayer,
ByBlock,
Default,
Value(i16),
}
impl LineWeight {
pub fn from_value(value: i16) -> Self {
match value {
-1 => LineWeight::ByLayer,
-2 => LineWeight::ByBlock,
-3 => LineWeight::Default,
v => LineWeight::Value(v),
}
}
pub fn value(&self) -> i16 {
match self {
LineWeight::ByLayer => -1,
LineWeight::ByBlock => -2,
LineWeight::Default => -3,
LineWeight::Value(v) => *v,
}
}
pub fn as_i16(&self) -> i16 {
self.value()
}
const INDEXED_VALUES: [i16; 24] = [
0, 5, 9, 13, 15, 18, 20, 25, 30, 35, 40, 50,
53, 60, 70, 80, 90, 100, 106, 120, 140, 158, 200, 211,
];
pub fn to_dwg_index(&self) -> u8 {
match self {
LineWeight::Default => 31,
LineWeight::ByBlock => 30,
LineWeight::ByLayer => 29,
LineWeight::Value(v) => {
Self::INDEXED_VALUES
.iter()
.position(|&w| w == *v)
.map(|i| i as u8)
.unwrap_or(31) }
}
}
pub fn from_dwg_index(index: u8) -> Self {
match index {
28 | 29 => LineWeight::ByLayer,
30 => LineWeight::ByBlock,
31 => LineWeight::Default,
i if (i as usize) < Self::INDEXED_VALUES.len() => {
LineWeight::Value(Self::INDEXED_VALUES[i as usize])
}
_ => LineWeight::Default,
}
}
pub fn millimeters(&self) -> Option<f64> {
match self {
LineWeight::Value(v) => Some(*v as f64 / 100.0),
_ => None,
}
}
pub const W0_00: LineWeight = LineWeight::Value(0);
pub const W0_05: LineWeight = LineWeight::Value(5);
pub const W0_09: LineWeight = LineWeight::Value(9);
pub const W0_13: LineWeight = LineWeight::Value(13);
pub const W0_15: LineWeight = LineWeight::Value(15);
pub const W0_18: LineWeight = LineWeight::Value(18);
pub const W0_20: LineWeight = LineWeight::Value(20);
pub const W0_25: LineWeight = LineWeight::Value(25);
pub const W0_30: LineWeight = LineWeight::Value(30);
pub const W0_35: LineWeight = LineWeight::Value(35);
pub const W0_40: LineWeight = LineWeight::Value(40);
pub const W0_50: LineWeight = LineWeight::Value(50);
pub const W0_53: LineWeight = LineWeight::Value(53);
pub const W0_60: LineWeight = LineWeight::Value(60);
pub const W0_70: LineWeight = LineWeight::Value(70);
pub const W0_80: LineWeight = LineWeight::Value(80);
pub const W0_90: LineWeight = LineWeight::Value(90);
pub const W1_00: LineWeight = LineWeight::Value(100);
pub const W1_06: LineWeight = LineWeight::Value(106);
pub const W1_20: LineWeight = LineWeight::Value(120);
pub const W1_40: LineWeight = LineWeight::Value(140);
pub const W1_58: LineWeight = LineWeight::Value(158);
pub const W2_00: LineWeight = LineWeight::Value(200);
pub const W2_11: LineWeight = LineWeight::Value(211);
}
impl fmt::Display for LineWeight {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
LineWeight::ByLayer => write!(f, "ByLayer"),
LineWeight::ByBlock => write!(f, "ByBlock"),
LineWeight::Default => write!(f, "Default"),
LineWeight::Value(v) => write!(f, "{:.2}mm", *v as f64 / 100.0),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_line_weight_from_value() {
assert_eq!(LineWeight::from_value(-1), LineWeight::ByLayer);
assert_eq!(LineWeight::from_value(-2), LineWeight::ByBlock);
assert_eq!(LineWeight::from_value(-3), LineWeight::Default);
assert_eq!(LineWeight::from_value(25), LineWeight::Value(25));
}
#[test]
fn test_line_weight_value() {
assert_eq!(LineWeight::ByLayer.value(), -1);
assert_eq!(LineWeight::Value(50).value(), 50);
}
#[test]
fn test_line_weight_millimeters() {
assert_eq!(LineWeight::Value(25).millimeters(), Some(0.25));
assert_eq!(LineWeight::Value(100).millimeters(), Some(1.0));
assert_eq!(LineWeight::ByLayer.millimeters(), None);
}
#[test]
fn test_line_weight_constants() {
assert_eq!(LineWeight::W0_25.millimeters(), Some(0.25));
assert_eq!(LineWeight::W1_00.millimeters(), Some(1.0));
}
#[test]
fn test_line_weight_display() {
assert_eq!(LineWeight::ByLayer.to_string(), "ByLayer");
assert_eq!(LineWeight::W0_25.to_string(), "0.25mm");
}
#[test]
fn test_default_line_weight() {
assert_eq!(LineWeight::default(), LineWeight::ByLayer);
}
#[test]
fn test_dwg_index_roundtrip_special() {
assert_eq!(LineWeight::Default.to_dwg_index(), 31);
assert_eq!(LineWeight::ByBlock.to_dwg_index(), 30);
assert_eq!(LineWeight::ByLayer.to_dwg_index(), 29);
assert_eq!(LineWeight::from_dwg_index(31), LineWeight::Default);
assert_eq!(LineWeight::from_dwg_index(30), LineWeight::ByBlock);
assert_eq!(LineWeight::from_dwg_index(29), LineWeight::ByLayer);
assert_eq!(LineWeight::from_dwg_index(28), LineWeight::ByLayer); }
#[test]
fn test_dwg_index_roundtrip_standard() {
assert_eq!(LineWeight::W0_00.to_dwg_index(), 0);
assert_eq!(LineWeight::W0_25.to_dwg_index(), 7);
assert_eq!(LineWeight::W2_11.to_dwg_index(), 23);
assert_eq!(LineWeight::from_dwg_index(0), LineWeight::W0_00);
assert_eq!(LineWeight::from_dwg_index(7), LineWeight::W0_25);
assert_eq!(LineWeight::from_dwg_index(23), LineWeight::W2_11);
}
}