dxfscan 0.1.0

Binary DXF parser with typed entity data and lookup indices
Documentation
// SPDX-License-Identifier: ISC
use crate::point::Point3;
use crate::value::GroupValue;
use alloc::vec::Vec;

/// A VERTEX entity within a [`Polyline`].
#[derive(Debug, Clone, Copy, Default)]
pub struct Vertex {
    /// Vertex location.
    pub location: Point3,
    /// Bulge factor.
    ///
    /// The tangent of one quarter of the arc's included angle for the
    /// segment starting at this vertex. Zero means a straight segment.
    /// Positive values produce counter-clockwise arcs; negative values
    /// produce clockwise arcs. A bulge of 1.0 is a semicircle.
    pub bulge: f64,
    /// Starting width for this segment.
    pub start_width: f64,
    /// Ending width for this segment.
    pub end_width: f64,
    /// Curve fit tangent direction in degrees.
    pub tangent_direction: f64,
    /// Vertex flags.
    ///
    /// `0b1` = extra vertex from curve fitting, `0b10` = curve fit
    /// tangent defined, `0b1000` = spline vertex from spline fitting,
    /// `0b1_0000` = spline frame control point,
    /// `0b100_0000` = 3D polyline vertex,
    /// `0b1000_0000` = polyface mesh face record.
    pub flags: i16,
    /// Polyface vertex indices.
    ///
    /// Used only when this vertex is a polyface face record
    /// (`flags & 0b1000_0000`). Each element is a 1-based index into
    /// the polyline's vertex list. Negative values indicate the edge
    /// following that vertex is invisible.
    pub polyface_vertex_index: [i16; 4],
}

impl Vertex {
    pub(crate) fn feed(&mut self, code: u16, val: &GroupValue) {
        match code {
            70 => {
                if let Some(v) = val.as_i16() {
                    self.flags = v;
                }
            }
            71 => {
                if let Some(v) = val.as_i16() {
                    self.polyface_vertex_index[0] = v;
                }
            }
            72 => {
                if let Some(v) = val.as_i16() {
                    self.polyface_vertex_index[1] = v;
                }
            }
            73 => {
                if let Some(v) = val.as_i16() {
                    self.polyface_vertex_index[2] = v;
                }
            }
            74 => {
                if let Some(v) = val.as_i16() {
                    self.polyface_vertex_index[3] = v;
                }
            }
            _ => {
                if let Some(f) = val.as_f64() {
                    match code {
                        10 => self.location.x = f,
                        20 => self.location.y = f,
                        30 => self.location.z = f,
                        40 => self.start_width = f,
                        41 => self.end_width = f,
                        42 => self.bulge = f,
                        50 => self.tangent_direction = f,
                        _ => {}
                    }
                }
            }
        }
    }
}

/// A POLYLINE entity.
///
/// Covers 2D/3D polylines, polygon meshes (`0b1_0000`), and polyface
/// meshes (`0b100_0000`). Child VERTEX entities are collected between
/// the POLYLINE and its SEQEND.
#[derive(Debug, Clone, Default)]
pub struct Polyline {
    /// Polyline flags.
    ///
    /// `0b1` = closed in M direction, `0b10` = curve-fit vertices
    /// added, `0b100` = spline-fit vertices added,
    /// `0b1000` = 3D polyline, `0b1_0000` = polygon mesh,
    /// `0b10_0000` = closed in N direction (mesh),
    /// `0b100_0000` = polyface mesh.
    pub flags: i16,
    /// Mesh M vertex count.
    pub vertex_count_m: i16,
    /// Mesh N vertex count.
    pub vertex_count_n: i16,
    /// Smooth surface density M.
    pub smooth_surface_density_m: i16,
    /// Smooth surface density N.
    pub smooth_surface_density_n: i16,
    /// Surface type.
    pub surface_type: i16,
    /// Elevation for 2D polylines.
    pub elevation: f64,
    /// Extrusion thickness.
    pub thickness: f64,
    /// Default start width.
    pub start_width: f64,
    /// Default end width.
    pub end_width: f64,
    /// Child VERTEX entities collected between POLYLINE and SEQEND.
    pub vertices: Vec<Vertex>,
}

impl Polyline {
    /// Returns `true` if the closed flag (`0b1`) is set.
    pub fn is_closed(&self) -> bool {
        self.flags & 1 != 0
    }

    pub(crate) fn feed(&mut self, code: u16, val: &GroupValue) {
        match code {
            70 => {
                if let Some(v) = val.as_i16() {
                    self.flags = v;
                }
            }
            71 => {
                if let Some(v) = val.as_i16() {
                    self.vertex_count_m = v;
                }
            }
            72 => {
                if let Some(v) = val.as_i16() {
                    self.vertex_count_n = v;
                }
            }
            73 => {
                if let Some(v) = val.as_i16() {
                    self.smooth_surface_density_m = v;
                }
            }
            74 => {
                if let Some(v) = val.as_i16() {
                    self.smooth_surface_density_n = v;
                }
            }
            75 => {
                if let Some(v) = val.as_i16() {
                    self.surface_type = v;
                }
            }
            _ => {
                if let Some(f) = val.as_f64() {
                    match code {
                        30 => self.elevation = f,
                        39 => self.thickness = f,
                        40 => self.start_width = f,
                        41 => self.end_width = f,
                        _ => {}
                    }
                }
            }
        }
    }
}