use crate::entities::EntityCommon;
use crate::types::{Matrix3, Transform, Vector3};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum DimensionType {
Linear = 0,
Aligned = 1,
Angular = 2,
Diameter = 3,
Radius = 4,
Angular3Point = 5,
Ordinate = 6,
ArcLength = 8,
LargeRadial = 9,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum AttachmentPointType {
TopLeft = 1,
TopCenter = 2,
TopRight = 3,
MiddleLeft = 4,
MiddleCenter = 5,
MiddleRight = 6,
BottomLeft = 7,
BottomCenter = 8,
BottomRight = 9,
}
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct DimensionBase {
pub common: EntityCommon,
pub definition_point: Vector3,
pub text_middle_point: Vector3,
pub insertion_point: Vector3,
pub dimension_type: DimensionType,
pub attachment_point: AttachmentPointType,
pub text: String,
pub user_text: Option<String>,
pub normal: Vector3,
pub text_rotation: f64,
pub horizontal_direction: f64,
pub style_name: String,
pub actual_measurement: f64,
pub version: u8,
pub block_name: String,
pub line_spacing_factor: f64,
pub line_spacing_style: i16,
pub insertion_scale: Vector3,
pub insertion_rotation: f64,
pub dwg_unknown_bit: bool,
pub flip_arrow1: bool,
pub flip_arrow2: bool,
pub dwg_flags_byte: u8,
pub text_user_positioned: bool,
}
impl DimensionBase {
pub fn new(dim_type: DimensionType) -> Self {
Self {
common: EntityCommon::default(),
definition_point: Vector3::new(0.0, 0.0, 0.0),
text_middle_point: Vector3::new(0.0, 0.0, 0.0),
insertion_point: Vector3::new(0.0, 0.0, 0.0),
dimension_type: dim_type,
attachment_point: AttachmentPointType::MiddleCenter,
text: String::new(),
user_text: None,
normal: Vector3::new(0.0, 0.0, 1.0),
text_rotation: 0.0,
horizontal_direction: 0.0,
style_name: "Standard".to_string(),
actual_measurement: 0.0,
version: 0,
block_name: String::new(),
line_spacing_factor: 1.0,
line_spacing_style: 1,
insertion_scale: Vector3::new(1.0, 1.0, 1.0),
insertion_rotation: 0.0,
dwg_unknown_bit: false,
flip_arrow1: false,
flip_arrow2: false,
dwg_flags_byte: 0x01,
text_user_positioned: false,
}
}
pub fn with_text(mut self, text: impl Into<String>) -> Self {
self.set_text_override(Some(text.into()));
self
}
pub fn text_override(&self) -> Option<&str> {
self.user_text
.as_deref()
.or_else(|| (!self.text.is_empty()).then_some(self.text.as_str()))
}
pub fn set_text_override(&mut self, text: Option<String>) {
self.text = text.clone().unwrap_or_default();
self.user_text = text;
}
pub fn with_style(mut self, style: impl Into<String>) -> Self {
self.style_name = style.into();
self
}
pub fn with_normal(mut self, normal: Vector3) -> Self {
self.normal = normal;
self
}
pub fn is_angular(&self) -> bool {
matches!(
self.dimension_type,
DimensionType::Angular | DimensionType::Angular3Point
)
}
}
impl Default for DimensionBase {
fn default() -> Self {
Self::new(DimensionType::Linear)
}
}
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct DimensionAligned {
pub base: DimensionBase,
pub first_point: Vector3,
pub second_point: Vector3,
pub definition_point: Vector3,
pub ext_line_rotation: f64,
}
impl DimensionAligned {
pub fn new(first_point: Vector3, second_point: Vector3) -> Self {
let mut base = DimensionBase::new(DimensionType::Aligned);
base.actual_measurement = first_point.distance(&second_point);
Self {
base,
first_point,
second_point,
definition_point: Vector3::ZERO,
ext_line_rotation: 0.0,
}
}
pub fn measurement(&self) -> f64 {
self.first_point.distance(&self.second_point)
}
pub fn set_offset(&mut self, offset: f64) {
let dir = self.second_point - self.first_point;
let perpendicular = Vector3::new(-dir.y, dir.x, 0.0).normalize();
self.definition_point = self.second_point + perpendicular * offset;
}
pub fn offset(&self) -> f64 {
self.second_point.distance(&self.definition_point)
}
}
impl Default for DimensionAligned {
fn default() -> Self {
Self {
base: DimensionBase::new(DimensionType::Aligned),
first_point: Vector3::ZERO,
second_point: Vector3::ZERO,
definition_point: Vector3::ZERO,
ext_line_rotation: 0.0,
}
}
}
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct DimensionLinear {
pub base: DimensionBase,
pub first_point: Vector3,
pub second_point: Vector3,
pub definition_point: Vector3,
pub rotation: f64,
pub ext_line_rotation: f64,
}
impl DimensionLinear {
pub fn new(first_point: Vector3, second_point: Vector3) -> Self {
let mut base = DimensionBase::new(DimensionType::Linear);
base.actual_measurement = first_point.distance(&second_point);
Self {
base,
first_point,
second_point,
definition_point: Vector3::ZERO,
rotation: 0.0,
ext_line_rotation: 0.0,
}
}
pub fn horizontal(first_point: Vector3, second_point: Vector3) -> Self {
Self::new(first_point, second_point)
}
pub fn vertical(first_point: Vector3, second_point: Vector3) -> Self {
let mut dim = Self::new(first_point, second_point);
dim.rotation = std::f64::consts::FRAC_PI_2; dim
}
pub fn rotated(first_point: Vector3, second_point: Vector3, angle: f64) -> Self {
let mut dim = Self::new(first_point, second_point);
dim.rotation = angle;
dim
}
pub fn measurement(&self) -> f64 {
let wcs_to_ocs = Matrix3::arbitrary_axis(self.base.normal).transpose();
let diff = wcs_to_ocs * (self.second_point - self.first_point);
let projected = diff.x * self.rotation.cos() + diff.y * self.rotation.sin();
if projected.is_finite() {
projected.abs()
} else {
0.0
}
}
pub fn set_offset(&mut self, offset: f64) {
let axis_y = Vector3::new(-self.rotation.sin(), self.rotation.cos(), 0.0);
self.definition_point = self.second_point + axis_y * offset;
}
}
impl Default for DimensionLinear {
fn default() -> Self {
Self {
base: DimensionBase::new(DimensionType::Linear),
first_point: Vector3::ZERO,
second_point: Vector3::ZERO,
definition_point: Vector3::ZERO,
rotation: 0.0,
ext_line_rotation: 0.0,
}
}
}
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct DimensionRadius {
pub base: DimensionBase,
pub definition_point: Vector3,
pub angle_vertex: Vector3,
pub leader_length: f64,
}
impl DimensionRadius {
pub fn new(center: Vector3, point_on_arc: Vector3) -> Self {
let mut base = DimensionBase::new(DimensionType::Radius);
base.actual_measurement = center.distance(&point_on_arc);
Self {
base,
definition_point: point_on_arc,
angle_vertex: center,
leader_length: 0.0,
}
}
pub fn measurement(&self) -> f64 {
self.definition_point.distance(&self.angle_vertex)
}
}
impl Default for DimensionRadius {
fn default() -> Self {
Self {
base: DimensionBase::new(DimensionType::Radius),
definition_point: Vector3::ZERO,
angle_vertex: Vector3::ZERO,
leader_length: 0.0,
}
}
}
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct DimensionDiameter {
pub base: DimensionBase,
pub definition_point: Vector3,
pub angle_vertex: Vector3,
pub leader_length: f64,
}
impl DimensionDiameter {
pub fn new(chord_point: Vector3, far_chord_point: Vector3) -> Self {
let mut base = DimensionBase::new(DimensionType::Diameter);
base.definition_point = far_chord_point;
base.actual_measurement = chord_point.distance(&far_chord_point);
Self {
base,
definition_point: far_chord_point,
angle_vertex: chord_point,
leader_length: 0.0,
}
}
pub fn measurement(&self) -> f64 {
self.definition_point.distance(&self.angle_vertex)
}
pub fn center(&self) -> Vector3 {
(self.angle_vertex + self.definition_point) * 0.5
}
}
impl Default for DimensionDiameter {
fn default() -> Self {
Self {
base: DimensionBase::new(DimensionType::Diameter),
definition_point: Vector3::ZERO,
angle_vertex: Vector3::ZERO,
leader_length: 0.0,
}
}
}
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct DimensionAngular2Ln {
pub base: DimensionBase,
pub dimension_arc: Vector3,
pub first_point: Vector3,
pub second_point: Vector3,
pub angle_vertex: Vector3,
pub definition_point: Vector3,
}
impl DimensionAngular2Ln {
pub fn new(vertex: Vector3, first_point: Vector3, second_point: Vector3) -> Self {
let mut base = DimensionBase::new(DimensionType::Angular);
let v1 = (first_point - vertex).normalize();
let v2 = (second_point - vertex).normalize();
let angle = v1.dot(&v2).acos();
base.actual_measurement = angle;
Self {
base,
dimension_arc: Vector3::ZERO,
first_point: vertex,
second_point: first_point,
angle_vertex: vertex,
definition_point: second_point,
}
}
pub fn measurement_radians(&self) -> f64 {
let first_direction = self.second_point - self.first_point;
let second_direction = self.definition_point - self.angle_vertex;
let Some(vertex) = line_intersection(
self.first_point,
first_direction,
self.angle_vertex,
second_direction,
) else {
return minor_angle_radians(first_direction, second_direction);
};
selected_line_sector_radians(
vertex,
first_direction,
second_direction,
self.dimension_arc,
self.base.normal,
)
.unwrap_or_else(|| minor_angle_radians(first_direction, second_direction))
}
pub fn measurement_degrees(&self) -> f64 {
self.measurement_radians().to_degrees()
}
}
impl Default for DimensionAngular2Ln {
fn default() -> Self {
Self {
base: DimensionBase::new(DimensionType::Angular),
dimension_arc: Vector3::ZERO,
first_point: Vector3::ZERO,
second_point: Vector3::ZERO,
angle_vertex: Vector3::ZERO,
definition_point: Vector3::ZERO,
}
}
}
pub type DimensionAngular2Line = DimensionAngular2Ln;
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct DimensionAngular3Pt {
pub base: DimensionBase,
pub definition_point: Vector3,
pub first_point: Vector3,
pub second_point: Vector3,
pub angle_vertex: Vector3,
}
impl DimensionAngular3Pt {
pub fn new(vertex: Vector3, first_point: Vector3, second_point: Vector3) -> Self {
let mut base = DimensionBase::new(DimensionType::Angular3Point);
let v1 = (first_point - vertex).normalize();
let v2 = (second_point - vertex).normalize();
let angle = v1.dot(&v2).acos();
base.actual_measurement = angle;
Self {
base,
definition_point: Vector3::ZERO,
angle_vertex: vertex,
first_point,
second_point,
}
}
pub fn measurement_radians(&self) -> f64 {
let first_direction = self.first_point - self.angle_vertex;
let second_direction = self.second_point - self.angle_vertex;
selected_line_sector_radians(
self.angle_vertex,
first_direction,
second_direction,
self.definition_point,
self.base.normal,
)
.unwrap_or_else(|| minor_angle_radians(first_direction, second_direction))
}
pub fn measurement_degrees(&self) -> f64 {
self.measurement_radians().to_degrees()
}
}
impl Default for DimensionAngular3Pt {
fn default() -> Self {
Self {
base: DimensionBase::new(DimensionType::Angular3Point),
definition_point: Vector3::ZERO,
first_point: Vector3::ZERO,
second_point: Vector3::ZERO,
angle_vertex: Vector3::ZERO,
}
}
}
pub type DimensionAngular3Point = DimensionAngular3Pt;
fn minor_angle_radians(first: Vector3, second: Vector3) -> f64 {
let first_length = first.length();
let second_length = second.length();
if first_length <= f64::EPSILON || second_length <= f64::EPSILON {
return 0.0;
}
(first.dot(&second) / (first_length * second_length))
.clamp(-1.0, 1.0)
.acos()
}
fn line_intersection(
first_origin: Vector3,
first_direction: Vector3,
second_origin: Vector3,
second_direction: Vector3,
) -> Option<Vector3> {
let cross = first_direction.cross(&second_direction);
let denominator = cross.length_squared();
let direction_scale = first_direction.length_squared() * second_direction.length_squared();
if !denominator.is_finite() || denominator <= direction_scale * 1.0e-24 {
return None;
}
let offset = second_origin - first_origin;
let first_parameter = offset.cross(&second_direction).dot(&cross) / denominator;
let second_parameter = offset.cross(&first_direction).dot(&cross) / denominator;
let first_point = first_origin + first_direction * first_parameter;
let second_point = second_origin + second_direction * second_parameter;
let scale = first_point.length().max(second_point.length()).max(1.0);
(first_point.distance(&second_point) <= scale * 1.0e-9)
.then_some((first_point + second_point) * 0.5)
}
fn selected_line_sector_radians(
vertex: Vector3,
first_direction: Vector3,
second_direction: Vector3,
arc_point: Vector3,
preferred_normal: Vector3,
) -> Option<f64> {
if first_direction.length_squared() <= f64::EPSILON
|| second_direction.length_squared() <= f64::EPSILON
{
return None;
}
let arc_direction = arc_point - vertex;
if arc_direction.length_squared() <= f64::EPSILON {
return None;
}
let cross = first_direction.cross(&second_direction);
let preferred_scale =
preferred_normal.length() * first_direction.length().max(second_direction.length());
let preferred_is_normal = preferred_normal.length_squared() > f64::EPSILON
&& preferred_normal.dot(&first_direction).abs() <= preferred_scale * 1.0e-9
&& preferred_normal.dot(&second_direction).abs() <= preferred_scale * 1.0e-9;
let normal = if preferred_is_normal {
preferred_normal.normalize()
} else if cross.length_squared() > f64::EPSILON {
cross.normalize()
} else {
return None;
};
let axis_x = first_direction.normalize();
let axis_y = normal.cross(&axis_x).normalize();
let normalize_angle = |vector: Vector3| {
vector
.dot(&axis_y)
.atan2(vector.dot(&axis_x))
.rem_euclid(std::f64::consts::TAU)
};
let first = normalize_angle(first_direction);
let second = normalize_angle(second_direction);
let selected = normalize_angle(arc_direction);
let mut boundaries = [
first,
(first + std::f64::consts::PI).rem_euclid(std::f64::consts::TAU),
second,
(second + std::f64::consts::PI).rem_euclid(std::f64::consts::TAU),
];
boundaries.sort_by(f64::total_cmp);
for index in 0..boundaries.len() {
let start = boundaries[index];
let end = if index + 1 < boundaries.len() {
boundaries[index + 1]
} else {
boundaries[0] + std::f64::consts::TAU
};
let selected = if selected + 1.0e-12 < start {
selected + std::f64::consts::TAU
} else {
selected
};
if selected >= start - 1.0e-12 && selected <= end + 1.0e-12 {
return Some((end - start).clamp(0.0, std::f64::consts::PI));
}
}
None
}
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct DimensionOrdinate {
pub base: DimensionBase,
pub definition_point: Vector3,
pub feature_location: Vector3,
pub leader_endpoint: Vector3,
pub is_ordinate_type_x: bool,
}
impl DimensionOrdinate {
pub fn new(feature_location: Vector3, leader_endpoint: Vector3, is_x_type: bool) -> Self {
let mut value = Self {
base: DimensionBase::new(DimensionType::Ordinate),
definition_point: Vector3::ZERO,
feature_location,
leader_endpoint,
is_ordinate_type_x: is_x_type,
};
value.refresh_measurement();
value
}
pub fn x_ordinate(feature_location: Vector3, leader_endpoint: Vector3) -> Self {
Self::new(feature_location, leader_endpoint, true)
}
pub fn y_ordinate(feature_location: Vector3, leader_endpoint: Vector3) -> Self {
Self::new(feature_location, leader_endpoint, false)
}
pub fn measurement(&self) -> f64 {
let delta = self.feature_location - self.definition_point;
let wcs_to_ocs = Matrix3::arbitrary_axis(self.base.normal).transpose();
let delta = wcs_to_ocs * delta;
let angle = -self.base.horizontal_direction;
let (sin, cos) = angle.sin_cos();
let projected = if self.is_ordinate_type_x {
delta.x * cos + delta.y * sin
} else {
-delta.x * sin + delta.y * cos
};
projected.abs()
}
pub fn refresh_measurement(&mut self) {
self.base.actual_measurement = self.measurement();
}
pub fn local_axes(&self) -> (Vector3, Vector3) {
let basis = Matrix3::arbitrary_axis(self.base.normal);
let angle = -self.base.horizontal_direction;
let (sin, cos) = angle.sin_cos();
(
basis * Vector3::new(cos, sin, 0.0),
basis * Vector3::new(-sin, cos, 0.0),
)
}
pub fn leader_polyline(
&self,
dogleg_length: f64,
extension_offset: f64,
fixed_extension_length: Option<f64>,
) -> [Vector3; 4] {
let (x_axis, y_axis) = self.local_axes();
let (main_axis, landing_axis) = if self.is_ordinate_type_x {
(y_axis, x_axis)
} else {
(x_axis, y_axis)
};
let delta = self.leader_endpoint - self.feature_location;
let signed = |value: f64| if value < 0.0 { -1.0 } else { 1.0 };
let main_direction = main_axis * signed(delta.dot(&main_axis));
let landing_direction = landing_axis * signed(delta.dot(&landing_axis));
let main_distance = delta.dot(&main_direction).abs();
let dogleg = dogleg_length.max(0.0);
let first_leg = (main_distance - 2.0 * dogleg).max(dogleg);
let elbow = self.feature_location + main_direction * first_leg;
let landing_start = self.leader_endpoint - landing_direction * dogleg;
let extension_start = if let Some(length) = fixed_extension_length {
elbow - main_direction * length.max(0.0)
} else {
self.feature_location + main_direction * extension_offset.max(0.0)
};
[extension_start, elbow, landing_start, self.leader_endpoint]
}
}
impl Default for DimensionOrdinate {
fn default() -> Self {
Self {
base: DimensionBase::new(DimensionType::Ordinate),
definition_point: Vector3::ZERO,
feature_location: Vector3::ZERO,
leader_endpoint: Vector3::ZERO,
is_ordinate_type_x: true,
}
}
}
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct DimensionArc {
pub base: DimensionBase,
pub definition_point: Vector3,
pub first_extension_point: Vector3,
pub second_extension_point: Vector3,
pub center_point: Vector3,
pub is_partial: bool,
pub arc_start_parameter: f64,
pub arc_end_parameter: f64,
pub has_leader: bool,
pub first_leader_point: Vector3,
pub second_leader_point: Vector3,
}
impl DimensionArc {
pub fn measurement(&self) -> f64 {
let radius = self.center_point.distance(&self.first_extension_point);
let raw_sweep = self.arc_end_parameter - self.arc_start_parameter;
let mut sweep = raw_sweep.rem_euclid(std::f64::consts::TAU);
if sweep <= 1.0e-12 && raw_sweep.abs() > 1.0e-12 {
sweep = std::f64::consts::TAU;
}
if sweep <= 1.0e-12 && raw_sweep.abs() <= 1.0e-12 {
let start = (self.first_extension_point.y - self.center_point.y)
.atan2(self.first_extension_point.x - self.center_point.x);
let end = (self.second_extension_point.y - self.center_point.y)
.atan2(self.second_extension_point.x - self.center_point.x);
sweep = (end - start).rem_euclid(std::f64::consts::TAU);
}
radius * sweep
}
}
impl Default for DimensionArc {
fn default() -> Self {
Self {
base: DimensionBase::new(DimensionType::ArcLength),
definition_point: Vector3::ZERO,
first_extension_point: Vector3::ZERO,
second_extension_point: Vector3::ZERO,
center_point: Vector3::ZERO,
is_partial: false,
arc_start_parameter: 0.0,
arc_end_parameter: 0.0,
has_leader: false,
first_leader_point: Vector3::ZERO,
second_leader_point: Vector3::ZERO,
}
}
}
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct DimensionLargeRadial {
pub base: DimensionBase,
pub definition_point: Vector3,
pub chord_point: Vector3,
pub jog_angle: f64,
pub override_center: Vector3,
pub jog_point: Vector3,
}
impl DimensionLargeRadial {
pub fn measurement(&self) -> f64 {
self.definition_point.distance(&self.chord_point)
}
}
impl Default for DimensionLargeRadial {
fn default() -> Self {
Self {
base: DimensionBase::new(DimensionType::LargeRadial),
definition_point: Vector3::ZERO,
chord_point: Vector3::ZERO,
jog_angle: 0.0,
override_center: Vector3::ZERO,
jog_point: Vector3::ZERO,
}
}
}
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum Dimension {
Aligned(DimensionAligned),
Linear(DimensionLinear),
Radius(DimensionRadius),
Diameter(DimensionDiameter),
Angular2Ln(DimensionAngular2Ln),
Angular3Pt(DimensionAngular3Pt),
Ordinate(DimensionOrdinate),
Arc(DimensionArc),
LargeRadial(DimensionLargeRadial),
}
impl Dimension {
pub fn base(&self) -> &DimensionBase {
match self {
Dimension::Aligned(d) => &d.base,
Dimension::Linear(d) => &d.base,
Dimension::Radius(d) => &d.base,
Dimension::Diameter(d) => &d.base,
Dimension::Angular2Ln(d) => &d.base,
Dimension::Angular3Pt(d) => &d.base,
Dimension::Ordinate(d) => &d.base,
Dimension::Arc(d) => &d.base,
Dimension::LargeRadial(d) => &d.base,
}
}
pub fn base_mut(&mut self) -> &mut DimensionBase {
match self {
Dimension::Aligned(d) => &mut d.base,
Dimension::Linear(d) => &mut d.base,
Dimension::Radius(d) => &mut d.base,
Dimension::Diameter(d) => &mut d.base,
Dimension::Angular2Ln(d) => &mut d.base,
Dimension::Angular3Pt(d) => &mut d.base,
Dimension::Ordinate(d) => &mut d.base,
Dimension::Arc(d) => &mut d.base,
Dimension::LargeRadial(d) => &mut d.base,
}
}
pub fn definition_point(&self) -> Vector3 {
match self {
Dimension::Aligned(d) => d.definition_point,
Dimension::Linear(d) => d.definition_point,
Dimension::Radius(d) => d.definition_point,
Dimension::Diameter(d) => d.definition_point,
Dimension::Angular2Ln(d) => d.definition_point,
Dimension::Angular3Pt(d) => d.definition_point,
Dimension::Ordinate(d) => d.definition_point,
Dimension::Arc(d) => d.definition_point,
Dimension::LargeRadial(d) => d.definition_point,
}
}
pub fn set_definition_point(&mut self, point: Vector3) {
match self {
Dimension::Aligned(d) => d.definition_point = point,
Dimension::Linear(d) => d.definition_point = point,
Dimension::Radius(d) => d.definition_point = point,
Dimension::Diameter(d) => d.definition_point = point,
Dimension::Angular2Ln(d) => d.definition_point = point,
Dimension::Angular3Pt(d) => d.definition_point = point,
Dimension::Ordinate(d) => d.definition_point = point,
Dimension::Arc(d) => d.definition_point = point,
Dimension::LargeRadial(d) => d.definition_point = point,
}
self.base_mut().definition_point = point;
}
pub fn measurement(&self) -> f64 {
match self {
Dimension::Aligned(d) => d.measurement(),
Dimension::Linear(d) => d.measurement(),
Dimension::Radius(d) => d.measurement(),
Dimension::Diameter(d) => d.measurement(),
Dimension::Angular2Ln(d) => d.measurement_degrees(),
Dimension::Angular3Pt(d) => d.measurement_degrees(),
Dimension::Ordinate(d) => d.measurement(),
Dimension::Arc(d) => d.measurement(),
Dimension::LargeRadial(d) => d.measurement(),
}
}
pub fn stored_measurement(&self) -> f64 {
match self {
Dimension::Angular2Ln(d) => d.measurement_radians(),
Dimension::Angular3Pt(d) => d.measurement_radians(),
_ => self.measurement(),
}
}
}
impl super::Entity for Dimension {
fn common(&self) -> &super::EntityCommon {
&self.base().common
}
fn common_mut(&mut self) -> &mut super::EntityCommon {
&mut self.base_mut().common
}
fn bounding_box(&self) -> crate::types::BoundingBox3D {
use crate::types::BoundingBox3D;
match self {
Dimension::Aligned(d) => {
BoundingBox3D::from_points(&[d.first_point, d.second_point, d.definition_point])
.unwrap_or_default()
}
Dimension::Linear(d) => {
BoundingBox3D::from_points(&[d.first_point, d.second_point, d.definition_point])
.unwrap_or_default()
}
Dimension::Radius(d) => {
BoundingBox3D::from_points(&[d.angle_vertex, d.definition_point])
.unwrap_or_default()
}
Dimension::Diameter(d) => {
BoundingBox3D::from_points(&[d.angle_vertex, d.definition_point])
.unwrap_or_default()
}
Dimension::Angular2Ln(d) => BoundingBox3D::from_points(&[
d.dimension_arc,
d.angle_vertex,
d.first_point,
d.second_point,
d.definition_point,
])
.unwrap_or_default(),
Dimension::Angular3Pt(d) => BoundingBox3D::from_points(&[
d.angle_vertex,
d.first_point,
d.second_point,
d.definition_point,
])
.unwrap_or_default(),
Dimension::Ordinate(d) => {
BoundingBox3D::from_points(&[d.feature_location, d.leader_endpoint])
.unwrap_or_default()
}
Dimension::Arc(d) => BoundingBox3D::from_points(&[
d.definition_point,
d.first_extension_point,
d.second_extension_point,
d.center_point,
d.first_leader_point,
d.second_leader_point,
])
.unwrap_or_default(),
Dimension::LargeRadial(d) => BoundingBox3D::from_points(&[
d.definition_point,
d.chord_point,
d.override_center,
d.jog_point,
])
.unwrap_or_default(),
}
}
fn translate(&mut self, offset: Vector3) {
super::translate::translate_dimension(self, offset);
}
fn apply_transform(&mut self, transform: &Transform) {
super::transform::transform_dimension(self, transform);
}
fn entity_type(&self) -> &'static str {
match self {
Dimension::Aligned(_) => "DIMENSION_ALIGNED",
Dimension::Linear(_) => "DIMENSION_LINEAR",
Dimension::Radius(_) => "DIMENSION_RADIUS",
Dimension::Diameter(_) => "DIMENSION_DIAMETER",
Dimension::Angular2Ln(_) => "DIMENSION_ANGULAR_2LINE",
Dimension::Angular3Pt(_) => "DIMENSION_ANGULAR_3POINT",
Dimension::Ordinate(_) => "DIMENSION_ORDINATE",
Dimension::Arc(_) => "ARC_DIMENSION",
Dimension::LargeRadial(_) => "LARGE_RADIAL_DIMENSION",
}
}
}