Align angular dimension properties and rendering
This commit is contained in:
parent
e93815d0c5
commit
04d824974d
3 changed files with 269 additions and 48 deletions
|
|
@ -1144,6 +1144,31 @@ pub(super) fn on_tab_close(&mut self, idx: usize) -> Task<Message> {
|
||||||
| GripMenuAction::MoveWithLeader
|
| GripMenuAction::MoveWithLeader
|
||||||
| GripMenuAction::MoveIndependent
|
| GripMenuAction::MoveIndependent
|
||||||
) {
|
) {
|
||||||
|
let is_dimension = matches!(
|
||||||
|
self.tabs[i].scene.document.get_entity(popup.handle),
|
||||||
|
Some(acadrust::EntityType::Dimension(_))
|
||||||
|
);
|
||||||
|
if is_dimension {
|
||||||
|
let movement = match item.action {
|
||||||
|
GripMenuAction::MoveWithDimLine => Some("Keep dim line with text"),
|
||||||
|
GripMenuAction::MoveWithLeader => Some("Move text, add leader"),
|
||||||
|
GripMenuAction::MoveIndependent => Some("Move text, no leader"),
|
||||||
|
_ => None,
|
||||||
|
};
|
||||||
|
if let Some(movement) = movement {
|
||||||
|
crate::entities::dim_override::set_property(
|
||||||
|
&mut self.tabs[i].scene.document,
|
||||||
|
popup.handle,
|
||||||
|
"dim_text_movement",
|
||||||
|
movement,
|
||||||
|
);
|
||||||
|
self.tabs[i].dirty = true;
|
||||||
|
self.tabs[i].scene.bump_entities(&[(
|
||||||
|
popup.handle,
|
||||||
|
crate::scene::ChangeKind::Modified,
|
||||||
|
)]);
|
||||||
|
}
|
||||||
|
}
|
||||||
// Stretch / Move = grab this grip. Engage it so the next
|
// Stretch / Move = grab this grip. Engage it so the next
|
||||||
// click places it (click-move-click) — same as picking the
|
// click places it (click-move-click) — same as picking the
|
||||||
// grip directly in the viewport. Without this the menu just
|
// grip directly in the viewport. Without this the menu just
|
||||||
|
|
@ -1157,10 +1182,12 @@ pub(super) fn on_tab_close(&mut self, idx: usize) -> Task<Message> {
|
||||||
// "Move with Leader" drags the whole multileader; the
|
// "Move with Leader" drags the whole multileader; the
|
||||||
// others move just the picked grip.
|
// others move just the picked grip.
|
||||||
let (grip_id, is_translate) =
|
let (grip_id, is_translate) =
|
||||||
if matches!(item.action, GripMenuAction::MoveWithLeader) {
|
if matches!(item.action, GripMenuAction::MoveWithLeader)
|
||||||
|
&& !is_dimension
|
||||||
|
{
|
||||||
(crate::entities::multileader::MOVE_ALL_GRIP, true)
|
(crate::entities::multileader::MOVE_ALL_GRIP, true)
|
||||||
} else {
|
} else {
|
||||||
(popup.grip_id, g.is_midpoint)
|
(popup.grip_id, if is_dimension { false } else { g.is_midpoint })
|
||||||
};
|
};
|
||||||
self.tabs[i].active_grip = Some(GripEdit::single(
|
self.tabs[i].active_grip = Some(GripEdit::single(
|
||||||
popup.handle,
|
popup.handle,
|
||||||
|
|
|
||||||
|
|
@ -274,6 +274,8 @@ pub fn property_int_code(field: &str) -> Option<i16> {
|
||||||
"dim_line_inside" => DIMSOXD,
|
"dim_line_inside" => DIMSOXD,
|
||||||
"dim_units" => DIMLUNIT,
|
"dim_units" => DIMLUNIT,
|
||||||
"dim_precision" => DIMDEC,
|
"dim_precision" => DIMDEC,
|
||||||
|
"dim_angle_units" => DIMAUNIT,
|
||||||
|
"dim_angle_precision" => DIMADEC,
|
||||||
"dim_decimal_separator" => DIMDSEP,
|
"dim_decimal_separator" => DIMDSEP,
|
||||||
"dim_fractional_type" => DIMFRAC,
|
"dim_fractional_type" => DIMFRAC,
|
||||||
"dim_text_view_direction" => DIMTXTDIRECTION,
|
"dim_text_view_direction" => DIMTXTDIRECTION,
|
||||||
|
|
@ -330,6 +332,9 @@ fn inherited_int(doc: &CadDocument, handle: Handle, code: i16) -> i16 {
|
||||||
DIMTOL => style.dimtol as i16,
|
DIMTOL => style.dimtol as i16,
|
||||||
DIMLIM => style.dimlim as i16,
|
DIMLIM => style.dimlim as i16,
|
||||||
DIMALT => style.dimalt as i16,
|
DIMALT => style.dimalt as i16,
|
||||||
|
DIMAZIN => style.dimazin,
|
||||||
|
DIMAUNIT => style.dimaunit,
|
||||||
|
DIMADEC => style.dimadec,
|
||||||
DIMTFILL => style.dimtfill,
|
DIMTFILL => style.dimtfill,
|
||||||
DIMTALN => 0,
|
DIMTALN => 0,
|
||||||
_ => 0,
|
_ => 0,
|
||||||
|
|
@ -451,6 +456,8 @@ pub fn set_property(
|
||||||
"dim_tolerance_suppress_trailing_zeros" => Some((DIMTZIN, 8)),
|
"dim_tolerance_suppress_trailing_zeros" => Some((DIMTZIN, 8)),
|
||||||
"dim_alt_tolerance_suppress_leading_zeros" => Some((DIMALTTZ, 4)),
|
"dim_alt_tolerance_suppress_leading_zeros" => Some((DIMALTTZ, 4)),
|
||||||
"dim_alt_tolerance_suppress_trailing_zeros" => Some((DIMALTTZ, 8)),
|
"dim_alt_tolerance_suppress_trailing_zeros" => Some((DIMALTTZ, 8)),
|
||||||
|
"dim_angle_suppress_leading_zeros" => Some((DIMAZIN, 1)),
|
||||||
|
"dim_angle_suppress_trailing_zeros" => Some((DIMAZIN, 2)),
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
if let Some((code, bit)) = bit_field {
|
if let Some((code, bit)) = bit_field {
|
||||||
|
|
@ -624,6 +631,13 @@ pub fn set_property(
|
||||||
"desktop" => Some(6),
|
"desktop" => Some(6),
|
||||||
_ => trimmed.parse().ok(),
|
_ => trimmed.parse().ok(),
|
||||||
},
|
},
|
||||||
|
"dim_angle_units" => match trimmed.to_ascii_lowercase().as_str() {
|
||||||
|
"decimal degrees" => Some(0),
|
||||||
|
"degrees/minutes/seconds" => Some(1),
|
||||||
|
"gradians" => Some(2),
|
||||||
|
"radians" => Some(3),
|
||||||
|
_ => trimmed.parse().ok(),
|
||||||
|
},
|
||||||
"dim_fractional_type" => match trimmed.to_ascii_lowercase().as_str() {
|
"dim_fractional_type" => match trimmed.to_ascii_lowercase().as_str() {
|
||||||
"horizontal" => Some(0),
|
"horizontal" => Some(0),
|
||||||
"diagonal" => Some(1),
|
"diagonal" => Some(1),
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ fn dimension_definition_point(dim: &Dimension) -> acadrust::types::Vector3 {
|
||||||
Dimension::Linear(d) => d.definition_point,
|
Dimension::Linear(d) => d.definition_point,
|
||||||
Dimension::Radius(d) => d.definition_point,
|
Dimension::Radius(d) => d.definition_point,
|
||||||
Dimension::Diameter(d) => d.definition_point,
|
Dimension::Diameter(d) => d.definition_point,
|
||||||
Dimension::Angular2Ln(d) => d.definition_point,
|
Dimension::Angular2Ln(d) => d.dimension_arc,
|
||||||
Dimension::Angular3Pt(d) => d.definition_point,
|
Dimension::Angular3Pt(d) => d.definition_point,
|
||||||
Dimension::Ordinate(d) => d.definition_point,
|
Dimension::Ordinate(d) => d.definition_point,
|
||||||
Dimension::Arc(d) => d.definition_point,
|
Dimension::Arc(d) => d.definition_point,
|
||||||
|
|
@ -107,6 +107,18 @@ fn properties(dim: &Dimension) -> Vec<PropSection> {
|
||||||
],
|
],
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
if matches!(dim, Dimension::Angular2Ln(_) | Dimension::Angular3Pt(_)) {
|
||||||
|
return vec![PropSection {
|
||||||
|
title: t!("Misc").into_owned(),
|
||||||
|
props: vec![crate::scene::model::object::Property {
|
||||||
|
label: t!("Dimension style").into_owned(),
|
||||||
|
field: "style_name",
|
||||||
|
value: crate::scene::model::object::PropValue::PlainText(
|
||||||
|
dim.base().style_name.clone(),
|
||||||
|
),
|
||||||
|
}],
|
||||||
|
}];
|
||||||
|
}
|
||||||
let mut props = base_props(dim.base());
|
let mut props = base_props(dim.base());
|
||||||
match dim {
|
match dim {
|
||||||
Dimension::Aligned(d) => {
|
Dimension::Aligned(d) => {
|
||||||
|
|
@ -1024,6 +1036,12 @@ fn restore_dim_text_relative_position(
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dimension_line_grip_position(dim: &Dimension) -> Option<DVec3> {
|
fn dimension_line_grip_position(dim: &Dimension) -> Option<DVec3> {
|
||||||
|
match dim {
|
||||||
|
Dimension::Angular2Ln(d) => return Some(dv3(&d.dimension_arc)),
|
||||||
|
Dimension::Angular3Pt(d) => return Some(dv3(&d.definition_point)),
|
||||||
|
Dimension::Arc(d) => return Some(dv3(&d.definition_point)),
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
let (first, second, defpt, ax, ay) = match dim {
|
let (first, second, defpt, ax, ay) = match dim {
|
||||||
Dimension::Linear(d) => (
|
Dimension::Linear(d) => (
|
||||||
d.first_point,
|
d.first_point,
|
||||||
|
|
@ -1139,11 +1157,12 @@ impl Grippable for Dimension {
|
||||||
center_grip(2, text),
|
center_grip(2, text),
|
||||||
],
|
],
|
||||||
Dimension::Angular2Ln(d) => vec![
|
Dimension::Angular2Ln(d) => vec![
|
||||||
square_grip(0, dv3(&d.angle_vertex)),
|
square_grip(0, dv3(&d.first_point)),
|
||||||
center_grip(1, dv3(&d.first_point)),
|
center_grip(1, dv3(&d.second_point)),
|
||||||
center_grip(2, dv3(&d.second_point)),
|
center_grip(2, dv3(&d.angle_vertex)),
|
||||||
center_grip(3, dv3(&d.definition_point)),
|
center_grip(3, dv3(&d.definition_point)),
|
||||||
center_grip(4, text),
|
center_grip(4, dv3(&d.dimension_arc)),
|
||||||
|
center_grip(5, text),
|
||||||
],
|
],
|
||||||
Dimension::Angular3Pt(d) => vec![
|
Dimension::Angular3Pt(d) => vec![
|
||||||
square_grip(0, dv3(&d.angle_vertex)),
|
square_grip(0, dv3(&d.angle_vertex)),
|
||||||
|
|
@ -1191,7 +1210,8 @@ impl Grippable for Dimension {
|
||||||
let text_grip = match self {
|
let text_grip = match self {
|
||||||
Dimension::Linear(_) | Dimension::Aligned(_) => 3,
|
Dimension::Linear(_) | Dimension::Aligned(_) => 3,
|
||||||
Dimension::Radius(_) | Dimension::Diameter(_) => 2,
|
Dimension::Radius(_) | Dimension::Diameter(_) => 2,
|
||||||
Dimension::Angular2Ln(_) | Dimension::Angular3Pt(_) => 4,
|
Dimension::Angular2Ln(_) => 5,
|
||||||
|
Dimension::Angular3Pt(_) => 4,
|
||||||
Dimension::Ordinate(_) => 3,
|
Dimension::Ordinate(_) => 3,
|
||||||
Dimension::Arc(d) => if d.has_leader { 6 } else { 4 },
|
Dimension::Arc(d) => if d.has_leader { 6 } else { 4 },
|
||||||
Dimension::LargeRadial(_) => 4,
|
Dimension::LargeRadial(_) => 4,
|
||||||
|
|
@ -1234,10 +1254,11 @@ impl Grippable for Dimension {
|
||||||
_ => {}
|
_ => {}
|
||||||
},
|
},
|
||||||
Dimension::Angular2Ln(d) => match grip_id {
|
Dimension::Angular2Ln(d) => match grip_id {
|
||||||
0 => apply_to_v3(&mut d.angle_vertex, &apply),
|
0 => apply_to_v3(&mut d.first_point, &apply),
|
||||||
1 => apply_to_v3(&mut d.first_point, &apply),
|
1 => apply_to_v3(&mut d.second_point, &apply),
|
||||||
2 => apply_to_v3(&mut d.second_point, &apply),
|
2 => apply_to_v3(&mut d.angle_vertex, &apply),
|
||||||
3 => apply_to_v3(&mut d.definition_point, &apply),
|
3 => apply_to_v3(&mut d.definition_point, &apply),
|
||||||
|
4 => apply_to_v3(&mut d.dimension_arc, &apply),
|
||||||
_ => {}
|
_ => {}
|
||||||
},
|
},
|
||||||
Dimension::Angular3Pt(d) => match grip_id {
|
Dimension::Angular3Pt(d) => match grip_id {
|
||||||
|
|
@ -1285,7 +1306,8 @@ impl Grippable for Dimension {
|
||||||
let (dim_line_grip, text_grip) = match self {
|
let (dim_line_grip, text_grip) = match self {
|
||||||
Dimension::Linear(_) | Dimension::Aligned(_) => (2, 3),
|
Dimension::Linear(_) | Dimension::Aligned(_) => (2, 3),
|
||||||
Dimension::Radius(_) | Dimension::Diameter(_) => (1, 2),
|
Dimension::Radius(_) | Dimension::Diameter(_) => (1, 2),
|
||||||
Dimension::Angular2Ln(_) | Dimension::Angular3Pt(_) => (3, 4),
|
Dimension::Angular2Ln(_) => (4, 5),
|
||||||
|
Dimension::Angular3Pt(_) => (3, 4),
|
||||||
Dimension::Ordinate(_) => (0, 3),
|
Dimension::Ordinate(_) => (0, 3),
|
||||||
Dimension::Arc(d) => (3, if d.has_leader { 6 } else { 4 }),
|
Dimension::Arc(d) => (3, if d.has_leader { 6 } else { 4 }),
|
||||||
Dimension::LargeRadial(_) => (3, 4),
|
Dimension::LargeRadial(_) => (3, 4),
|
||||||
|
|
@ -1353,7 +1375,8 @@ impl Grippable for Dimension {
|
||||||
let (_dim_line_grip, text_grip) = match self {
|
let (_dim_line_grip, text_grip) = match self {
|
||||||
Dimension::Linear(_) | Dimension::Aligned(_) => (2, 3),
|
Dimension::Linear(_) | Dimension::Aligned(_) => (2, 3),
|
||||||
Dimension::Radius(_) | Dimension::Diameter(_) => (1, 2),
|
Dimension::Radius(_) | Dimension::Diameter(_) => (1, 2),
|
||||||
Dimension::Angular2Ln(_) | Dimension::Angular3Pt(_) => (3, 4),
|
Dimension::Angular2Ln(_) => (4, 5),
|
||||||
|
Dimension::Angular3Pt(_) => (3, 4),
|
||||||
Dimension::Ordinate(_) => (0, 3),
|
Dimension::Ordinate(_) => (0, 3),
|
||||||
Dimension::Arc(d) => (3, if d.has_leader { 6 } else { 4 }),
|
Dimension::Arc(d) => (3, if d.has_leader { 6 } else { 4 }),
|
||||||
Dimension::LargeRadial(_) => (3, 4),
|
Dimension::LargeRadial(_) => (3, 4),
|
||||||
|
|
@ -1400,7 +1423,8 @@ impl Grippable for Dimension {
|
||||||
let text_grip = match self {
|
let text_grip = match self {
|
||||||
Dimension::Linear(_) | Dimension::Aligned(_) => 3,
|
Dimension::Linear(_) | Dimension::Aligned(_) => 3,
|
||||||
Dimension::Radius(_) | Dimension::Diameter(_) => 2,
|
Dimension::Radius(_) | Dimension::Diameter(_) => 2,
|
||||||
Dimension::Angular2Ln(_) | Dimension::Angular3Pt(_) => 4,
|
Dimension::Angular2Ln(_) => 5,
|
||||||
|
Dimension::Angular3Pt(_) => 4,
|
||||||
Dimension::Ordinate(_) => 3,
|
Dimension::Ordinate(_) => 3,
|
||||||
Dimension::Arc(d) => if d.has_leader { 6 } else { 4 },
|
Dimension::Arc(d) => if d.has_leader { 6 } else { 4 },
|
||||||
Dimension::LargeRadial(_) => 4,
|
Dimension::LargeRadial(_) => 4,
|
||||||
|
|
@ -1641,7 +1665,7 @@ pub fn style_sections(
|
||||||
_ => choice_value("None", &["None", "Background", "Color"]),
|
_ => choice_value("None", &["None", "Background", "Color"]),
|
||||||
};
|
};
|
||||||
|
|
||||||
vec![
|
let mut sections = vec![
|
||||||
PropSection {
|
PropSection {
|
||||||
title: t!("Lines & Arrows").into_owned(),
|
title: t!("Lines & Arrows").into_owned(),
|
||||||
props: vec![
|
props: vec![
|
||||||
|
|
@ -1968,19 +1992,19 @@ pub fn style_sections(
|
||||||
text(
|
text(
|
||||||
t!("Decimal separator").as_ref(),
|
t!("Decimal separator").as_ref(),
|
||||||
"dim_decimal_separator",
|
"dim_decimal_separator",
|
||||||
decimal_separator,
|
decimal_separator.clone(),
|
||||||
true,
|
true,
|
||||||
),
|
),
|
||||||
text(
|
text(
|
||||||
t!("Dim prefix").as_ref(),
|
t!("Dim prefix").as_ref(),
|
||||||
"dim_prefix",
|
"dim_prefix",
|
||||||
dim_prefix,
|
dim_prefix.clone(),
|
||||||
true,
|
true,
|
||||||
),
|
),
|
||||||
text(
|
text(
|
||||||
t!("Dim suffix").as_ref(),
|
t!("Dim suffix").as_ref(),
|
||||||
"dim_suffix",
|
"dim_suffix",
|
||||||
dim_suffix,
|
dim_suffix.clone(),
|
||||||
true,
|
true,
|
||||||
),
|
),
|
||||||
text(
|
text(
|
||||||
|
|
@ -2271,7 +2295,81 @@ pub fn style_sections(
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
]
|
];
|
||||||
|
|
||||||
|
if matches!(dimension, Dimension::Angular2Ln(_) | Dimension::Angular3Pt(_)) {
|
||||||
|
if let Some(text_section) = sections
|
||||||
|
.iter_mut()
|
||||||
|
.find(|section| section.title == t!("Text").as_ref())
|
||||||
|
{
|
||||||
|
text_section
|
||||||
|
.props
|
||||||
|
.retain(|property| property.field != "dim_fractional_type");
|
||||||
|
}
|
||||||
|
|
||||||
|
let angle_zero_suppression = int(ov::DIMAZIN, s.dimazin);
|
||||||
|
let angle_unit = int(ov::DIMAUNIT, s.dimaunit);
|
||||||
|
if let Some(primary_units) = sections
|
||||||
|
.iter_mut()
|
||||||
|
.find(|section| section.title == t!("Primary Units").as_ref())
|
||||||
|
{
|
||||||
|
primary_units.props = vec![
|
||||||
|
text(
|
||||||
|
t!("Decimal separator").as_ref(),
|
||||||
|
"dim_decimal_separator",
|
||||||
|
decimal_separator,
|
||||||
|
true,
|
||||||
|
),
|
||||||
|
text(t!("Dim prefix").as_ref(), "dim_prefix", dim_prefix, true),
|
||||||
|
text(t!("Dim suffix").as_ref(), "dim_suffix", dim_suffix, true),
|
||||||
|
choice(
|
||||||
|
t!("Angle format").as_ref(),
|
||||||
|
"dim_angle_units",
|
||||||
|
angular_unit_label(angle_unit),
|
||||||
|
&[
|
||||||
|
"Decimal degrees",
|
||||||
|
"Degrees/minutes/seconds",
|
||||||
|
"Gradians",
|
||||||
|
"Radians",
|
||||||
|
],
|
||||||
|
true,
|
||||||
|
),
|
||||||
|
choice(
|
||||||
|
t!("Suppress leading zeros").as_ref(),
|
||||||
|
"dim_angle_suppress_leading_zeros",
|
||||||
|
yes(angle_zero_suppression & 1 != 0),
|
||||||
|
&["Yes", "No"],
|
||||||
|
true,
|
||||||
|
),
|
||||||
|
choice(
|
||||||
|
t!("Suppress trailing zeros").as_ref(),
|
||||||
|
"dim_angle_suppress_trailing_zeros",
|
||||||
|
yes(angle_zero_suppression & 2 != 0),
|
||||||
|
&["Yes", "No"],
|
||||||
|
true,
|
||||||
|
),
|
||||||
|
property(
|
||||||
|
t!("Precision").as_ref(),
|
||||||
|
"dim_angle_precision",
|
||||||
|
PropValue::Choice {
|
||||||
|
selected: int(ov::DIMADEC, s.dimadec).to_string(),
|
||||||
|
options: (0..=8).map(|value| value.to_string()).collect(),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
sections.retain(|section| section.title != t!("Alternate Units").as_ref());
|
||||||
|
if let Some(tolerances) = sections
|
||||||
|
.iter_mut()
|
||||||
|
.find(|section| section.title == t!("Tolerances").as_ref())
|
||||||
|
{
|
||||||
|
tolerances
|
||||||
|
.props
|
||||||
|
.retain(|property| !property.field.starts_with("dim_alt_tolerance_"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sections
|
||||||
}
|
}
|
||||||
|
|
||||||
fn property(label: &str, field: &'static str, value: PropValue) -> Property {
|
fn property(label: &str, field: &'static str, value: PropValue) -> Property {
|
||||||
|
|
@ -2355,6 +2453,15 @@ fn alternate_unit_label(value: i16) -> &'static str {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn angular_unit_label(value: i16) -> &'static str {
|
||||||
|
match value {
|
||||||
|
1 => "Degrees/minutes/seconds",
|
||||||
|
2 => "Gradians",
|
||||||
|
3 => "Radians",
|
||||||
|
_ => "Decimal degrees",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn tolerance_vertical_label(value: i16) -> &'static str {
|
fn tolerance_vertical_label(value: i16) -> &'static str {
|
||||||
match value {
|
match value {
|
||||||
0 => "Bottom",
|
0 => "Bottom",
|
||||||
|
|
@ -3369,6 +3476,8 @@ fn dimtmove_leader_endpoints(dim: &Dimension) -> Option<(Vec3, Vec3)> {
|
||||||
}
|
}
|
||||||
Dimension::Radius(d) => lv(d.definition_point),
|
Dimension::Radius(d) => lv(d.definition_point),
|
||||||
Dimension::Diameter(d) => (lv(d.angle_vertex) + lv(d.definition_point)) * 0.5,
|
Dimension::Diameter(d) => (lv(d.angle_vertex) + lv(d.definition_point)) * 0.5,
|
||||||
|
Dimension::Angular2Ln(d) => lv(d.dimension_arc),
|
||||||
|
Dimension::Angular3Pt(d) => lv(d.definition_point),
|
||||||
_ => return None,
|
_ => return None,
|
||||||
};
|
};
|
||||||
Some((anchor, lv(txt)))
|
Some((anchor, lv(txt)))
|
||||||
|
|
@ -3566,7 +3675,12 @@ fn dimension_geometry(
|
||||||
// ten degrees came out as two hundred and seventy.
|
// ten degrees came out as two hundred and seventy.
|
||||||
let (p1, p2) = (lv(d.first_point), lv(d.second_point));
|
let (p1, p2) = (lv(d.first_point), lv(d.second_point));
|
||||||
let (p3, p4) = (lv(d.angle_vertex), lv(d.definition_point));
|
let (p3, p4) = (lv(d.angle_vertex), lv(d.definition_point));
|
||||||
let arc_point = lv(d.dimension_arc);
|
let stored_arc = if d.dimension_arc.length_squared() > 1.0e-18 {
|
||||||
|
d.dimension_arc
|
||||||
|
} else {
|
||||||
|
d.base.definition_point
|
||||||
|
};
|
||||||
|
let arc_point = lv(stored_arc);
|
||||||
match two_line_angle_frame(p1, p2, p3, p4, arc_point) {
|
match two_line_angle_frame(p1, p2, p3, p4, arc_point) {
|
||||||
Some((vertex, start, end)) => append_angular_dimension(
|
Some((vertex, start, end)) => append_angular_dimension(
|
||||||
&mut g,
|
&mut g,
|
||||||
|
|
@ -3577,6 +3691,8 @@ fn dimension_geometry(
|
||||||
arrow1,
|
arrow1,
|
||||||
arrow2,
|
arrow2,
|
||||||
Some((start, end)),
|
Some((start, end)),
|
||||||
|
params,
|
||||||
|
suppress,
|
||||||
),
|
),
|
||||||
// Parallel lines have no vertex and so no angle to draw; the
|
// Parallel lines have no vertex and so no angle to draw; the
|
||||||
// extension lines alone say where the dimension was.
|
// extension lines alone say where the dimension was.
|
||||||
|
|
@ -3587,15 +3703,29 @@ fn dimension_geometry(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Dimension::Angular3Pt(d) => {
|
Dimension::Angular3Pt(d) => {
|
||||||
|
let vertex = lv(d.angle_vertex);
|
||||||
|
let first = lv(d.first_point);
|
||||||
|
let second = lv(d.second_point);
|
||||||
|
let arc_point = lv(d.definition_point);
|
||||||
|
let explicit_sweep = two_line_angle_frame(
|
||||||
|
vertex,
|
||||||
|
first,
|
||||||
|
vertex,
|
||||||
|
second,
|
||||||
|
arc_point,
|
||||||
|
)
|
||||||
|
.map(|(_, start, end)| (start, end));
|
||||||
append_angular_dimension(
|
append_angular_dimension(
|
||||||
&mut g,
|
&mut g,
|
||||||
lv(d.angle_vertex),
|
vertex,
|
||||||
lv(d.first_point),
|
first,
|
||||||
lv(d.second_point),
|
second,
|
||||||
lv(d.definition_point),
|
arc_point,
|
||||||
arrow1,
|
arrow1,
|
||||||
arrow2,
|
arrow2,
|
||||||
None,
|
explicit_sweep,
|
||||||
|
params,
|
||||||
|
suppress,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Dimension::Ordinate(d) => {
|
Dimension::Ordinate(d) => {
|
||||||
|
|
@ -3623,6 +3753,8 @@ fn dimension_geometry(
|
||||||
d.arc_start_parameter as f32,
|
d.arc_start_parameter as f32,
|
||||||
d.arc_end_parameter as f32,
|
d.arc_end_parameter as f32,
|
||||||
)),
|
)),
|
||||||
|
params,
|
||||||
|
suppress,
|
||||||
);
|
);
|
||||||
if d.has_leader {
|
if d.has_leader {
|
||||||
add_segment(
|
add_segment(
|
||||||
|
|
@ -3933,6 +4065,8 @@ fn append_angular_dimension(
|
||||||
arrow1: &ArrowKind,
|
arrow1: &ArrowKind,
|
||||||
arrow2: &ArrowKind,
|
arrow2: &ArrowKind,
|
||||||
explicit_sweep: Option<(f32, f32)>,
|
explicit_sweep: Option<(f32, f32)>,
|
||||||
|
params: DimLineParams,
|
||||||
|
suppress: SuppressFlags,
|
||||||
) {
|
) {
|
||||||
let radius = vertex.distance(arc_point);
|
let radius = vertex.distance(arc_point);
|
||||||
if radius <= 1e-6 {
|
if radius <= 1e-6 {
|
||||||
|
|
@ -3947,8 +4081,30 @@ fn append_angular_dimension(
|
||||||
let (start, mut end) = explicit_sweep.unwrap_or((measured_start, measured_end));
|
let (start, mut end) = explicit_sweep.unwrap_or((measured_start, measured_end));
|
||||||
let dir1 = Vec3::new(start.cos(), start.sin(), 0.0);
|
let dir1 = Vec3::new(start.cos(), start.sin(), 0.0);
|
||||||
let dir2 = Vec3::new(end.cos(), end.sin(), 0.0);
|
let dir2 = Vec3::new(end.cos(), end.sin(), 0.0);
|
||||||
add_segment(&mut g.ext_lines, first, vertex + dir1 * radius);
|
let arc_start = vertex + dir1 * radius;
|
||||||
add_segment(&mut g.ext_lines, second, vertex + dir2 * radius);
|
let arc_end = vertex + dir2 * radius;
|
||||||
|
let extension = |origin: Vec3, endpoint: Vec3, direction: Vec3| {
|
||||||
|
if params.dimfxlon {
|
||||||
|
(
|
||||||
|
endpoint - direction * params.dimfxl.max(0.0),
|
||||||
|
endpoint + direction * params.dimexe,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
let toward_arc = normalized_or(endpoint - origin, direction);
|
||||||
|
(
|
||||||
|
origin + toward_arc * params.dimexo,
|
||||||
|
endpoint + toward_arc * params.dimexe,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let (ext1_start, ext1_end) = extension(first, arc_start, dir1);
|
||||||
|
let (ext2_start, ext2_end) = extension(second, arc_end, dir2);
|
||||||
|
if !suppress.ext1 {
|
||||||
|
add_segment(&mut g.ext_lines, ext1_start, ext1_end);
|
||||||
|
}
|
||||||
|
if !suppress.ext2 {
|
||||||
|
add_segment(&mut g.ext_lines, ext2_start, ext2_end);
|
||||||
|
}
|
||||||
|
|
||||||
let mut delta = end - start;
|
let mut delta = end - start;
|
||||||
// Wrap a negative sweep forwards, but leave a zero one alone: two rays that
|
// Wrap a negative sweep forwards, but leave a zero one alone: two rays that
|
||||||
|
|
@ -3965,14 +4121,28 @@ fn append_angular_dimension(
|
||||||
delta = end - start;
|
delta = end - start;
|
||||||
}
|
}
|
||||||
|
|
||||||
let steps = 32;
|
let arc_extension = if params.ticks && radius > 1.0e-6 {
|
||||||
|
params.dimdle / radius
|
||||||
|
} else {
|
||||||
|
0.0
|
||||||
|
};
|
||||||
|
let direction = delta.signum();
|
||||||
|
let draw_start = start - direction * arc_extension;
|
||||||
|
let draw_delta = delta + direction * arc_extension * 2.0;
|
||||||
|
let steps = angular_arc_steps(draw_delta);
|
||||||
let mut arc_pts = Vec::with_capacity((steps + 1) as usize);
|
let mut arc_pts = Vec::with_capacity((steps + 1) as usize);
|
||||||
for i in 0..=steps {
|
for i in 0..=steps {
|
||||||
let t = i as f32 / steps as f32;
|
let t = i as f32 / steps as f32;
|
||||||
let a = start + delta * t;
|
let a = draw_start + draw_delta * t;
|
||||||
arc_pts.push(vertex + Vec3::new(a.cos() * radius, a.sin() * radius, 0.0));
|
arc_pts.push(vertex + Vec3::new(a.cos() * radius, a.sin() * radius, 0.0));
|
||||||
}
|
}
|
||||||
add_polyline(&mut g.dim_lines, &arc_pts);
|
let midpoint = arc_pts.len() / 2;
|
||||||
|
if !suppress.dim1 && midpoint > 0 {
|
||||||
|
add_polyline(&mut g.dim_lines, &arc_pts[..=midpoint]);
|
||||||
|
}
|
||||||
|
if !suppress.dim2 && midpoint + 1 < arc_pts.len() {
|
||||||
|
add_polyline(&mut g.dim_lines, &arc_pts[midpoint..]);
|
||||||
|
}
|
||||||
|
|
||||||
if arc_pts.len() >= 2 {
|
if arc_pts.len() >= 2 {
|
||||||
append_arrow(
|
append_arrow(
|
||||||
|
|
@ -3991,6 +4161,10 @@ fn append_angular_dimension(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn angular_arc_steps(sweep: f32) -> u32 {
|
||||||
|
((sweep.abs() / std::f32::consts::PI * 90.0).ceil() as u32).clamp(8, 720)
|
||||||
|
}
|
||||||
|
|
||||||
fn dimension_snap_pts(dim: &Dimension) -> Vec<(glam::DVec3, SnapHint)> {
|
fn dimension_snap_pts(dim: &Dimension) -> Vec<(glam::DVec3, SnapHint)> {
|
||||||
let lv = |v: acadrust::types::Vector3| glam::DVec3::new(v.x, v.y, v.z);
|
let lv = |v: acadrust::types::Vector3| glam::DVec3::new(v.x, v.y, v.z);
|
||||||
let node = |v: acadrust::types::Vector3| (lv(v), SnapHint::Node);
|
let node = |v: acadrust::types::Vector3| (lv(v), SnapHint::Node);
|
||||||
|
|
@ -4008,10 +4182,11 @@ fn dimension_snap_pts(dim: &Dimension) -> Vec<(glam::DVec3, SnapHint)> {
|
||||||
Dimension::Radius(d) => vec![node(d.angle_vertex), node(d.definition_point)],
|
Dimension::Radius(d) => vec![node(d.angle_vertex), node(d.definition_point)],
|
||||||
Dimension::Diameter(d) => vec![node(d.angle_vertex), node(d.definition_point)],
|
Dimension::Diameter(d) => vec![node(d.angle_vertex), node(d.definition_point)],
|
||||||
Dimension::Angular2Ln(d) => vec![
|
Dimension::Angular2Ln(d) => vec![
|
||||||
node(d.angle_vertex),
|
|
||||||
node(d.first_point),
|
node(d.first_point),
|
||||||
node(d.second_point),
|
node(d.second_point),
|
||||||
|
node(d.angle_vertex),
|
||||||
node(d.definition_point),
|
node(d.definition_point),
|
||||||
|
node(d.dimension_arc),
|
||||||
],
|
],
|
||||||
Dimension::Angular3Pt(d) => vec![
|
Dimension::Angular3Pt(d) => vec![
|
||||||
node(d.angle_vertex),
|
node(d.angle_vertex),
|
||||||
|
|
@ -4771,35 +4946,44 @@ fn reduce_fraction(mut n: u64, mut d: u64) -> String {
|
||||||
/// Format an angular measurement (input in degrees as Dimension::measurement
|
/// Format an angular measurement (input in degrees as Dimension::measurement
|
||||||
/// returns for angular variants) honouring DIMAUNIT, DIMADEC, DIMAZIN.
|
/// returns for angular variants) honouring DIMAUNIT, DIMADEC, DIMAZIN.
|
||||||
fn format_angular_value(measurement_deg: f64, style: Option<&DimStyle>) -> String {
|
fn format_angular_value(measurement_deg: f64, style: Option<&DimStyle>) -> String {
|
||||||
let (aunit, adec, azin) = style
|
let (aunit, adec, azin, decimal_separator) = style
|
||||||
.map(|s| (s.dimaunit, s.dimadec, s.dimazin))
|
.map(|s| (s.dimaunit, s.dimadec, s.dimazin, s.dimdsep))
|
||||||
.unwrap_or((0, 2, 0));
|
.unwrap_or((0, 2, 0, b'.' as i16));
|
||||||
let adec = adec.max(0) as usize;
|
let adec = adec.max(0) as usize;
|
||||||
|
|
||||||
match aunit {
|
match aunit {
|
||||||
// 1 = Degrees / Minutes / Seconds
|
// 1 = Degrees / Minutes / Seconds
|
||||||
1 => format_dms(measurement_deg, adec, azin),
|
1 => format_dms(measurement_deg, adec, azin, decimal_separator),
|
||||||
// 2 = Gradians
|
// 2 = Gradians
|
||||||
2 => {
|
2 => {
|
||||||
let g = measurement_deg / 0.9;
|
let g = measurement_deg / 0.9;
|
||||||
let raw = format!("{:.*}", adec, g);
|
let raw = format!("{:.*}", adec, g);
|
||||||
format!("{}g", apply_angular_zero_suppression(&raw, azin))
|
format!(
|
||||||
|
"{}g",
|
||||||
|
swap_decimal_sep(&apply_angular_zero_suppression(&raw, azin), decimal_separator)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
// 3 = Radians
|
// 3 = Radians
|
||||||
3 => {
|
3 => {
|
||||||
let r = measurement_deg.to_radians();
|
let r = measurement_deg.to_radians();
|
||||||
let raw = format!("{:.*}", adec, r);
|
let raw = format!("{:.*}", adec, r);
|
||||||
format!("{}r", apply_angular_zero_suppression(&raw, azin))
|
format!(
|
||||||
|
"{}r",
|
||||||
|
swap_decimal_sep(&apply_angular_zero_suppression(&raw, azin), decimal_separator)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
// 0 or unknown = Decimal Degrees
|
// 0 or unknown = Decimal Degrees
|
||||||
_ => {
|
_ => {
|
||||||
let raw = format!("{:.*}", adec, measurement_deg);
|
let raw = format!("{:.*}", adec, measurement_deg);
|
||||||
format!("{}°", apply_angular_zero_suppression(&raw, azin))
|
format!(
|
||||||
|
"{}°",
|
||||||
|
swap_decimal_sep(&apply_angular_zero_suppression(&raw, azin), decimal_separator)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn format_dms(deg: f64, sec_dec: usize, azin: i16) -> String {
|
fn format_dms(deg: f64, sec_dec: usize, azin: i16, decimal_separator: i16) -> String {
|
||||||
let sign = if deg < 0.0 { "-" } else { "" };
|
let sign = if deg < 0.0 { "-" } else { "" };
|
||||||
let abs = deg.abs();
|
let abs = deg.abs();
|
||||||
let d = abs.floor();
|
let d = abs.floor();
|
||||||
|
|
@ -4807,15 +4991,11 @@ fn format_dms(deg: f64, sec_dec: usize, azin: i16) -> String {
|
||||||
let m = m_full.floor();
|
let m = m_full.floor();
|
||||||
let s = (m_full - m) * 60.0;
|
let s = (m_full - m) * 60.0;
|
||||||
let s_str = format!("{:.*}", sec_dec, s);
|
let s_str = format!("{:.*}", sec_dec, s);
|
||||||
let mut out = format!("{}{:.0}°{:.0}'{}\"", sign, d, m, s_str);
|
let s_str = swap_decimal_sep(
|
||||||
if azin & 4 != 0 {
|
&apply_angular_zero_suppression(&s_str, azin),
|
||||||
// suppress 0° / 0' parts
|
decimal_separator,
|
||||||
if d == 0.0 {
|
);
|
||||||
out = out.trim_start_matches('0').to_string();
|
format!("{}{:.0}°{:.0}'{}\"", sign, d, m, s_str)
|
||||||
out = out.replacen("°", "", 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
out
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Apply DIMZIN bit flags to a formatted linear value.
|
/// Apply DIMZIN bit flags to a formatted linear value.
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue