use super::{Entity, EntityCommon};
use crate::types::{BoundingBox3D, Color, Handle, LineWeight, Transform, Transparency, Vector3};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[repr(i16)]
pub enum SurfaceSmoothType {
NoSmooth = 0,
Quadratic = 5,
Cubic = 6,
Bezier = 8,
}
impl SurfaceSmoothType {
pub fn from_i16(v: i16) -> Self {
match v {
5 => SurfaceSmoothType::Quadratic,
6 => SurfaceSmoothType::Cubic,
8 => SurfaceSmoothType::Bezier,
_ => SurfaceSmoothType::NoSmooth,
}
}
}
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct PolygonMeshVertex {
pub common: EntityCommon,
pub location: Vector3,
pub flags: i16,
}
impl PolygonMeshVertex {
pub fn new() -> Self {
PolygonMeshVertex {
common: EntityCommon::new(),
location: Vector3::ZERO,
flags: 0,
}
}
pub fn at(location: Vector3) -> Self {
PolygonMeshVertex {
location,
..Self::new()
}
}
}
impl Default for PolygonMeshVertex {
fn default() -> Self {
Self::new()
}
}
bitflags::bitflags! {
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct PolygonMeshFlags: i16 {
const CLOSED_M = 1;
const CURVE_FIT = 2;
const SPLINE_FIT = 4;
const POLYGON_MESH = 16;
const CLOSED_N = 32;
const CONTINUOUS_LINETYPE = 128;
}
}
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct PolygonMesh {
pub common: EntityCommon,
pub flags: PolygonMeshFlags,
pub m_vertex_count: i16,
pub n_vertex_count: i16,
pub m_smooth_density: i16,
pub n_smooth_density: i16,
pub smooth_type: SurfaceSmoothType,
pub elevation: f64,
pub normal: Vector3,
pub vertices: Vec<PolygonMeshVertex>,
}
impl PolygonMesh {
pub fn new() -> Self {
PolygonMesh {
common: EntityCommon::new(),
flags: PolygonMeshFlags::POLYGON_MESH,
m_vertex_count: 0,
n_vertex_count: 0,
m_smooth_density: 0,
n_smooth_density: 0,
smooth_type: SurfaceSmoothType::NoSmooth,
elevation: 0.0,
normal: Vector3::UNIT_Z,
vertices: Vec::new(),
}
}
pub fn is_closed_m(&self) -> bool {
self.flags.contains(PolygonMeshFlags::CLOSED_M)
}
pub fn is_closed_n(&self) -> bool {
self.flags.contains(PolygonMeshFlags::CLOSED_N)
}
}
impl Default for PolygonMesh {
fn default() -> Self {
Self::new()
}
}
impl Entity for PolygonMesh {
fn handle(&self) -> Handle { self.common.handle }
fn set_handle(&mut self, handle: Handle) { self.common.handle = handle; }
fn layer(&self) -> &str { &self.common.layer }
fn set_layer(&mut self, layer: String) { self.common.layer = layer; }
fn color(&self) -> Color { self.common.color }
fn set_color(&mut self, color: Color) { self.common.color = color; }
fn line_weight(&self) -> LineWeight { self.common.line_weight }
fn set_line_weight(&mut self, weight: LineWeight) { self.common.line_weight = weight; }
fn transparency(&self) -> Transparency { self.common.transparency }
fn set_transparency(&mut self, transparency: Transparency) { self.common.transparency = transparency; }
fn is_invisible(&self) -> bool { self.common.invisible }
fn set_invisible(&mut self, invisible: bool) { self.common.invisible = invisible; }
fn bounding_box(&self) -> BoundingBox3D {
if self.vertices.is_empty() {
return BoundingBox3D::from_point(Vector3::ZERO);
}
let points: Vec<Vector3> = self.vertices.iter().map(|v| v.location).collect();
BoundingBox3D::from_points(&points).unwrap_or_else(|| BoundingBox3D::from_point(Vector3::ZERO))
}
fn translate(&mut self, offset: Vector3) {
super::translate::translate_polygon_mesh(self, offset);
}
fn entity_type(&self) -> &'static str { "POLYLINE" }
fn apply_transform(&mut self, transform: &Transform) {
super::transform::transform_polygon_mesh(self, transform);
}
}