use crate::entities::solid3d::{AcisData, Silhouette, Wire};
use crate::entities::{Entity, EntityCommon};
use crate::types::{BoundingBox3D, Color, Handle, LineWeight, Transparency, Vector3};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum SurfaceKind {
#[default]
Generic,
Plane,
Extruded,
Lofted,
Revolved,
Swept,
Nurb,
}
impl SurfaceKind {
pub fn from_dxf_name(name: &str) -> Self {
match name.to_uppercase().as_str() {
"PLANESURFACE" => SurfaceKind::Plane,
"EXTRUDEDSURFACE" => SurfaceKind::Extruded,
"LOFTEDSURFACE" => SurfaceKind::Lofted,
"REVOLVEDSURFACE" => SurfaceKind::Revolved,
"SWEPTSURFACE" => SurfaceKind::Swept,
"NURBSURFACE" => SurfaceKind::Nurb,
_ => SurfaceKind::Generic,
}
}
pub fn dxf_name(self) -> &'static str {
match self {
SurfaceKind::Generic => "SURFACE",
SurfaceKind::Plane => "PLANESURFACE",
SurfaceKind::Extruded => "EXTRUDEDSURFACE",
SurfaceKind::Lofted => "LOFTEDSURFACE",
SurfaceKind::Revolved => "REVOLVEDSURFACE",
SurfaceKind::Swept => "SWEPTSURFACE",
SurfaceKind::Nurb => "NURBSURFACE",
}
}
}
#[derive(Debug, Clone, PartialEq, Default)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Surface {
pub common: EntityCommon,
pub kind: SurfaceKind,
pub acis_data: AcisData,
pub wires: Vec<Wire>,
pub silhouettes: Vec<Silhouette>,
pub raw_dwg_data: Option<Vec<u8>>,
pub dwg_handle_bits: i64,
pub dwg_source_version: Option<crate::types::DxfVersion>,
}
impl Surface {
pub fn new(kind: SurfaceKind) -> Self {
Self {
common: EntityCommon::default(),
kind,
acis_data: AcisData::new(),
wires: Vec::new(),
silhouettes: Vec::new(),
raw_dwg_data: None,
dwg_handle_bits: 0,
dwg_source_version: None,
}
}
pub fn has_acis_data(&self) -> bool {
self.acis_data.has_data()
}
pub fn parse_sat(&self) -> Option<crate::entities::acis::SatDocument> {
if self.acis_data.is_binary || self.acis_data.sat_data.is_empty() {
return None;
}
crate::entities::acis::SatDocument::parse(&self.acis_data.sat_data).ok()
}
}
impl Entity for Surface {
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, line_weight: LineWeight) {
self.common.line_weight = line_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.wires.is_empty() {
return BoundingBox3D::default();
}
let mut min = Vector3::new(f64::MAX, f64::MAX, f64::MAX);
let mut max = Vector3::new(f64::MIN, f64::MIN, f64::MIN);
for wire in &self.wires {
for pt in &wire.points {
min.x = min.x.min(pt.x);
min.y = min.y.min(pt.y);
min.z = min.z.min(pt.z);
max.x = max.x.max(pt.x);
max.y = max.y.max(pt.y);
max.z = max.z.max(pt.z);
}
}
BoundingBox3D::new(min, max)
}
fn translate(&mut self, offset: Vector3) {
super::translate::translate_surface(self, offset);
}
fn entity_type(&self) -> &'static str {
"SURFACE"
}
fn apply_transform(&mut self, transform: &crate::types::Transform) {
super::transform::transform_surface(self, transform);
}
}