From 75f042607ec027d60a5703b2a81fa04ca8b442fa Mon Sep 17 00:00:00 2001 From: ramox81 <184937705+ramox81@users.noreply.github.com> Date: Tue, 25 Aug 2026 15:39:48 +0300 Subject: [PATCH] Align diameter properties and graphics --- src/entities/dim_override.rs | 25 +++ src/entities/dimension.rs | 338 ++++++++++++++++++++++++++--- src/modules/draw/modify/explode.rs | 179 +++++++++++++-- 3 files changed, 492 insertions(+), 50 deletions(-) diff --git a/src/entities/dim_override.rs b/src/entities/dim_override.rs index 13ce51b8a..868bbab64 100644 --- a/src/entities/dim_override.rs +++ b/src/entities/dim_override.rs @@ -352,6 +352,7 @@ fn inherited_real(doc: &CadDocument, handle: Handle, code: i16) -> f64 { }; match code { DIMGAP => style.dimgap, + DIMCEN => style.dimcen, DIMTP => style.dimtp, DIMTM => style.dimtm, _ => 0.0, @@ -390,6 +391,30 @@ pub fn set_property( value: &str, ) -> bool { let trimmed = value.trim(); + if field == "dim_center_type" { + let current = inherited_real(doc, handle, DIMCEN); + let size = current.abs().max(0.01); + let value = match trimmed.to_ascii_lowercase().as_str() { + "none" => 0.0, + "mark" => size, + "lines" => -size, + _ => return false, + }; + set(doc, handle, DIMCEN, Some(XDataValue::Real(value))); + return true; + } + if field == "dim_center_size" { + let Ok(size) = trimmed.parse::() else { + return false; + }; + if !size.is_finite() || size < 0.0 { + return false; + } + let current = inherited_real(doc, handle, DIMCEN); + let value = if current < 0.0 { -size } else { size }; + set(doc, handle, DIMCEN, Some(XDataValue::Real(value))); + return true; + } let handle_field = match field { "dim_arrowhead_1" => Some(DIMBLK1), "dim_arrowhead_2" => Some(DIMBLK2), diff --git a/src/entities/dimension.rs b/src/entities/dimension.rs index ae3032661..c633e27b6 100644 --- a/src/entities/dimension.rs +++ b/src/entities/dimension.rs @@ -86,6 +86,23 @@ fn base_props(base: &DimensionBase) -> Vec Vec { + if let Dimension::Diameter(diameter) = dim { + return vec![PropSection { + title: t!("Misc").into_owned(), + props: vec![ + Property { + label: t!("Dimension style").into_owned(), + field: "style_name", + value: PropValue::PlainText(diameter.base.style_name.clone()), + }, + edit( + t!("Leader Length").as_ref(), + "leader_length", + diameter.leader_length, + ), + ], + }]; + } let compact_linear = match dim { Dimension::Linear(d) => Some(( &d.base, @@ -1268,11 +1285,29 @@ impl Grippable for Dimension { 1 => apply_to_v3(&mut d.definition_point, &apply), _ => {} }, - Dimension::Diameter(d) => match grip_id { - 0 => apply_to_v3(&mut d.angle_vertex, &apply), - 1 => apply_to_v3(&mut d.definition_point, &apply), - _ => {} - }, + Dimension::Diameter(d) => { + let center = d.center(); + let radius = d.measurement() * 0.5; + let mut target = match grip_id { + 0 => d.angle_vertex, + 1 => d.definition_point, + _ => center, + }; + if grip_id <= 1 { + apply_to_v3(&mut target, &apply); + let offset = target - center; + if offset.length_squared() > 1e-24 && radius > 1e-12 { + let radial = offset.normalize() * radius; + if grip_id == 0 { + d.angle_vertex = center + radial; + d.definition_point = center - radial; + } else { + d.definition_point = center + radial; + d.angle_vertex = center - radial; + } + } + } + } Dimension::Angular2Ln(d) => match grip_id { 0 => apply_to_v3(&mut d.angle_vertex, &apply), 1 => apply_to_v3(&mut d.first_point, &apply), @@ -1636,8 +1671,15 @@ pub fn style_sections( let linetype = |code, inherited| { linetype_name(document, ov::handle(data, code).unwrap_or(inherited)) }; - let arrow_1 = arrow_name(ov::DIMBLK1, s.dimblk1, &s.dimblk1_name); - let arrow_2 = arrow_name(ov::DIMBLK2, s.dimblk2, &s.dimblk2_name); + let diameter_arrow = |code: i16, handle: acadrust::types::Handle, name: &str| { + if matches!(dimension, Dimension::Diameter(_)) && !s.dimsah && handle.is_null() { + arrow_name(code, s.dimblk, &s.dimblk_name) + } else { + arrow_name(code, handle, name) + } + }; + let arrow_1 = diameter_arrow(ov::DIMBLK1, s.dimblk1, &s.dimblk1_name); + let arrow_2 = diameter_arrow(ov::DIMBLK2, s.dimblk2, &s.dimblk2_name); for current in [&arrow_1, &arrow_2] { if !arrow_options.contains(current) { arrow_options.push(current.clone()); @@ -1682,7 +1724,7 @@ pub fn style_sections( _ => choice_value("None", &["None", "Background", "Color"]), }; - vec![ + let mut sections = vec![ PropSection { title: t!("Lines & Arrows").into_owned(), props: vec![ @@ -2312,7 +2354,68 @@ pub fn style_sections( ), ], }, - ] + ]; + + if matches!(dimension, Dimension::Diameter(_)) { + let dimcen = real(ov::DIMCEN, s.dimcen); + let center_type = if dimcen > 1e-12 { + "Mark" + } else if dimcen < -1e-12 { + "Lines" + } else { + "None" + }; + if let Some(lines) = sections + .iter_mut() + .find(|section| section.title == t!("Lines & Arrows").as_ref()) + { + const DIAMETER_LINE_FIELDS: &[&str] = &[ + "dim_arrowhead_1", + "dim_arrowhead_2", + "dim_arrow_size", + "dim_line_lineweight", + "dim_ext_line_lineweight", + "dim_line_1", + "dim_line_2", + "dim_line_color", + "dim_linetype", + "dim_ext_linetype_1", + "dim_ext_line_1", + "dim_ext_line_color", + "dim_ext_line_ext", + "dim_ext_line_offset", + ]; + lines + .props + .retain(|property| DIAMETER_LINE_FIELDS.contains(&property.field)); + lines.props.insert(3, choice( + t!("Center mark").as_ref(), + "dim_center_type", + center_type, + &["None", "Mark", "Lines"], + true, + )); + lines.props.insert(4, number( + t!("Center size").as_ref(), + "dim_center_size", + dimcen.abs(), + center_type != "None", + )); + } + if let Some(primary_units) = sections + .iter_mut() + .find(|section| section.title == t!("Primary Units").as_ref()) + { + primary_units.props.retain(|property| { + !matches!( + property.field, + "dim_sub_units_suffix" | "dim_sub_units_scale" + ) + }); + } + } + + sections } fn property(label: &str, field: &'static str, value: PropValue) -> Property { @@ -2835,7 +2938,33 @@ fn tessellate_dimension_inner( }; (t.clone(), t) } else if let Some(s) = style { - if dimsah { + if matches!(dim, Dimension::Diameter(_)) { + let data = &dim.base().common.extended_data; + let first = crate::entities::dim_override::handle( + data, + crate::entities::dim_override::DIMBLK1, + ) + .unwrap_or(if dimsah { s.dimblk1 } else { s.dimblk }); + let second = crate::entities::dim_override::handle( + data, + crate::entities::dim_override::DIMBLK2, + ) + .unwrap_or(if dimsah { s.dimblk2 } else { s.dimblk }); + ( + arrow_from_block_with_deferred_hatch( + document, + first, + dimasz, + defer_arrow_hatches, + ), + arrow_from_block_with_deferred_hatch( + document, + second, + dimasz, + defer_arrow_hatches, + ), + ) + } else if dimsah { ( arrow_from_block_with_deferred_hatch( document, @@ -2894,6 +3023,7 @@ fn tessellate_dimension_inner( None } }; + let text_position = vec3_local(dimension_text_pos_f64(dim, style, dim_txt, dim_scale)); let mut geom = dimension_geometry( dim, @@ -2912,6 +3042,8 @@ fn tessellate_dimension_inner( text_width, dimatfit: style.map(|s| s.dimatfit).unwrap_or(3), dimtofl: style.map(|s| s.dimtofl).unwrap_or(false), + text_position, + text_movement: style.map(|s| s.dimtmove).unwrap_or(0), text_break, }, SuppressFlags { @@ -2922,6 +3054,18 @@ fn tessellate_dimension_inner( }, ); + if !dimse1 { + if let Some(points) = crate::scene::dimension_assoc::radial_extension_points( + document, + handle, + dimexo as f64, + dimexe as f64, + ) { + let points: Vec = points.into_iter().map(vec3_local).collect(); + add_polyline(&mut geom.ext_lines, &points); + } + } + // DIMTMOVE = 1: when the saved text_middle_point sits far from the // dim-line anchor, draw a short leader connecting them. (=0 anchors text // to the dim line — no leader; =2 frees text without a leader.) @@ -3409,7 +3553,15 @@ fn dimtmove_leader_endpoints(dim: &Dimension) -> Option<(Vec3, Vec3)> { (first + perp * off1 + second + perp * off2) * 0.5 } Dimension::Radius(d) => lv(d.definition_point), - Dimension::Diameter(d) => (lv(d.angle_vertex) + lv(d.definition_point)) * 0.5, + Dimension::Diameter(d) => { + let chord = lv(d.angle_vertex); + let far_chord = lv(d.definition_point); + if chord.distance_squared(lv(txt)) <= far_chord.distance_squared(lv(txt)) { + chord + } else { + far_chord + } + } _ => return None, }; Some((anchor, lv(txt))) @@ -3479,6 +3631,8 @@ struct DimLineParams { text_width: f32, dimatfit: i16, dimtofl: bool, + text_position: Vec3, + text_movement: i16, /// Text box (local centre, half-width, half-height) used to break the /// dimension line where the text sits on it, so a DIMTFILL background reads /// over the line. None when the text doesn't overlap the line. @@ -3576,26 +3730,21 @@ fn dimension_geometry( append_center_mark(&mut g, center, params.dimcen, radius); } Dimension::Diameter(d) => { - // angle_vertex is the circle centre and definition_point a point on - // the circle. The diameter line runs edge-to-edge THROUGH the centre - // (far edge → near edge), with arrows pointing inward at each edge. - let center = lv(d.angle_vertex); - let edge = lv(d.definition_point); - let far = center * 2.0 - edge; - add_segment(&mut g.dim_lines, far, edge); - append_arrow(&mut g, edge, normalized_or(far - edge, Vec3::X), arrow1); - append_arrow(&mut g, far, normalized_or(edge - far, Vec3::X), arrow2); - // Diameter leader: continue past the near edge toward the text. - if d.leader_length.abs() > 1e-9 { - let text = dimension_text_position(dim); - let leader_dir = normalized_or(text - edge, edge - far); - add_segment( - &mut g.dim_lines, - edge, - edge + leader_dir * (d.leader_length as f32), - ); - } - let radius = (edge - center).length(); + // Diametric data stores the two opposite chord points directly. + let chord = lv(d.angle_vertex); + let far_chord = lv(d.definition_point); + append_diameter_dimension( + &mut g, + chord, + far_chord, + arrow1, + arrow2, + d.leader_length as f32, + params, + suppress, + ); + let center = (chord + far_chord) * 0.5; + let radius = chord.distance(far_chord) * 0.5; append_center_mark(&mut g, center, params.dimcen, radius); } Dimension::Angular2Ln(d) => { @@ -3862,6 +4011,107 @@ fn append_linear_dimension( } } +fn append_diameter_dimension( + g: &mut DimGeom, + chord: Vec3, + far_chord: Vec3, + arrow1: &ArrowKind, + arrow2: &ArrowKind, + leader_length: f32, + params: DimLineParams, + suppress: SuppressFlags, +) { + let axis = normalized_or(far_chord - chord, Vec3::X); + let diameter = chord.distance(far_chord); + if diameter <= 1e-6 { + return; + } + + let arrows_outside = if params.ticks || params.arrow_len <= 1e-6 { + false + } else if diameter < 2.0 * params.arrow_len { + true + } else if diameter < params.text_width + 2.0 * params.arrow_len { + match params.dimatfit { + 0 | 1 => true, + 2 => false, + _ => params.text_width <= diameter, + } + } else { + false + }; + + let extension = if params.ticks { params.dimdle } else { 0.0 }; + let first = chord - axis * extension; + let second = far_chord + axis * extension; + let line_length = first.distance(second); + let mut left_end = line_length * 0.5; + let mut right_start = left_end; + if let Some((text_center, half_width, half_height)) = params.text_break { + let along = (text_center - first).dot(axis); + if along > 0.0 && along < line_length { + left_end = along; + right_start = along; + let perpendicular = (text_center - (first + axis * along)).length(); + if perpendicular < half_height + && along - half_width > 0.0 + && along + half_width < line_length + { + left_end = along - half_width; + right_start = along + half_width; + } + } + } + + let draw_inside_line = !arrows_outside || params.dimtofl; + if draw_inside_line && !suppress.dim1 && left_end > 1e-6 { + add_segment(&mut g.dim_lines, first, first + axis * left_end); + } + if draw_inside_line && !suppress.dim2 && line_length - right_start > 1e-6 { + add_segment( + &mut g.dim_lines, + first + axis * right_start, + second, + ); + } + if arrows_outside && !params.dimsoxd { + let stub = params.arrow_len * 2.0; + if !suppress.dim1 { + add_segment(&mut g.dim_lines, chord - axis * stub, chord); + } + if !suppress.dim2 { + add_segment(&mut g.dim_lines, far_chord, far_chord + axis * stub); + } + } + + if arrows_outside { + append_arrow(g, chord, -axis, arrow1); + append_arrow(g, far_chord, axis, arrow2); + } else { + append_arrow(g, chord, axis, arrow1); + append_arrow(g, far_chord, -axis, arrow2); + } + + let text_along = (params.text_position - chord).dot(axis); + if params.text_movement == 0 { + let (tip, suppressed) = if params.text_position.distance_squared(chord) + <= params.text_position.distance_squared(far_chord) + { + (chord, suppress.dim1) + } else { + (far_chord, suppress.dim2) + }; + if !suppressed && leader_length.abs() > 1e-6 { + let direction = normalized_or(params.text_position - tip, axis); + add_segment(&mut g.dim_lines, tip, tip + direction * leader_length.abs()); + } else if text_along < 0.0 && !suppress.dim1 { + add_segment(&mut g.dim_lines, chord, params.text_position); + } else if text_along > diameter && !suppress.dim2 { + add_segment(&mut g.dim_lines, far_chord, params.text_position); + } + } +} + /// Draw a center mark for radius/diameter dimensions. /// DIMCEN > 0 → small "+" of half-length |DIMCEN| at the centre. /// DIMCEN < 0 → small "+" *plus* four line segments extending from the @@ -4299,6 +4549,11 @@ fn dimension_text_is_outside(dim: &Dimension, style: Option<&DimStyle>) -> bool let length = (delta.x * delta.x + delta.y * delta.y).sqrt().max(1e-12); (d.first_point, d.second_point, delta / length) } + Dimension::Diameter(d) => { + let delta = d.definition_point - d.angle_vertex; + let length = (delta.x * delta.x + delta.y * delta.y).sqrt().max(1e-12); + (d.angle_vertex, d.definition_point, delta / length) + } _ => return false, }; let first_axis = first.x * axis.x + first.y * axis.y; @@ -4338,6 +4593,8 @@ fn dimension_text_natural_rotation(dim: &Dimension) -> f64 { let dy = d.second_point.y - d.first_point.y; dy.atan2(dx) } + Dimension::Diameter(d) => (d.definition_point.y - d.angle_vertex.y) + .atan2(d.definition_point.x - d.angle_vertex.x), _ => 0.0, }; // Clamp to (-π/2, π/2] so text never appears upside-down. @@ -5119,6 +5376,25 @@ fn dimension_text_pos_f64( dimtad, ) } + Dimension::Diameter(d) => { + let dx = d.definition_point.x - d.angle_vertex.x; + let dy = d.definition_point.y - d.angle_vertex.y; + let len = (dx * dx + dy * dy).sqrt().max(1e-12); + text_on_dim_line( + d.angle_vertex, + d.definition_point, + d.angle_vertex, + dx / len, + dy / len, + dimjust, + perp_off, + text_w, + arrow, + dimtix, + dimatfit, + dimtad, + ) + } _ => { // Non-linear (radius / diameter / angular / ordinate): lift the // natural mid point straight up by the style offset. A user-dragged diff --git a/src/modules/draw/modify/explode.rs b/src/modules/draw/modify/explode.rs index 302033f9e..f4a3e4831 100644 --- a/src/modules/draw/modify/explode.rs +++ b/src/modules/draw/modify/explode.rs @@ -612,10 +612,66 @@ struct DimMetrics { /// suppression), DIMCLRD/E/T (colours) and DIMLWD/E (lineweights). fn dim_metrics(dim: &Dimension, doc: &CadDocument) -> DimMetrics { let name = dim.base().style_name.as_str(); - let style = doc.dim_styles.iter().find(|s| { + let mut effective_style = doc.dim_styles.iter().find(|s| { s.name.eq_ignore_ascii_case(name) || (name.trim().is_empty() && s.name.eq_ignore_ascii_case("Standard")) - }); + }).cloned(); + if let Some(style) = &mut effective_style { + use crate::entities::dim_override as ov; + let data = &dim.base().common.extended_data; + macro_rules! real { + ($field:ident, $code:ident) => { + if let Some(value) = ov::real(data, ov::$code) { + style.$field = value; + } + }; + } + macro_rules! int { + ($field:ident, $code:ident) => { + if let Some(value) = ov::int(data, ov::$code) { + style.$field = value; + } + }; + } + macro_rules! flag { + ($field:ident, $code:ident) => { + if let Some(value) = ov::int(data, ov::$code) { + style.$field = value != 0; + } + }; + } + macro_rules! handle { + ($field:ident, $code:ident) => { + if let Some(value) = ov::handle(data, ov::$code) { + style.$field = value; + } + }; + } + real!(dimscale, DIMSCALE); + real!(dimasz, DIMASZ); + real!(dimcen, DIMCEN); + real!(dimexo, DIMEXO); + real!(dimexe, DIMEXE); + real!(dimtsz, DIMTSZ); + real!(dimdle, DIMDLE); + real!(dimfxl, DIMFXL); + flag!(dimfxlon, DIMFXLON); + flag!(dimse1, DIMSE1); + flag!(dimse2, DIMSE2); + flag!(dimsd1, DIMSD1); + flag!(dimsd2, DIMSD2); + flag!(dimsoxd, DIMSOXD); + flag!(dimsah, DIMSAH); + int!(dimclrd, DIMCLRD); + int!(dimclre, DIMCLRE); + int!(dimclrt, DIMCLRT); + int!(dimlwd, DIMLWD); + int!(dimlwe, DIMLWE); + handle!(dimblk, DIMBLK); + handle!(dimblk1, DIMBLK1); + handle!(dimblk2, DIMBLK2); + } + let style = effective_style.as_ref(); let scale = style .map(|s| if s.dimscale > 1e-6 { s.dimscale } else { 1.0 }) .unwrap_or(1.0); @@ -630,7 +686,15 @@ fn dim_metrics(dim: &Dimension, doc: &CadDocument) -> DimMetrics { let t = ArrowKind::Tick { size: dimtsz as f32 }; (t.clone(), t) } else if let Some(s) = style { - if s.dimsah { + if matches!(dim, Dimension::Diameter(_)) { + use crate::entities::dim_override as ov; + let data = &dim.base().common.extended_data; + let first = ov::handle(data, ov::DIMBLK1) + .unwrap_or(if s.dimsah { s.dimblk1 } else { s.dimblk }); + let second = ov::handle(data, ov::DIMBLK2) + .unwrap_or(if s.dimsah { s.dimblk2 } else { s.dimblk }); + (arrow_from_block(doc, first, asz), arrow_from_block(doc, second, asz)) + } else if s.dimsah { (arrow_from_block(doc, s.dimblk1, asz), arrow_from_block(doc, s.dimblk2, asz)) } else { let a = arrow_from_block(doc, s.dimblk, asz); @@ -993,27 +1057,103 @@ fn explode_dimension(dim: &Dimension, doc: &CadDocument) -> Vec { result.extend(dim_center_mark(center, met.dimcen, len, &dim_c)); } Dimension::Diameter(d) => { - // Full diameter through the centre (far edge -> near edge), inward - // terminators at both edges, plus the centre mark. - let (center, edge) = (d.angle_vertex, d.definition_point); - let far = v3(2.0 * center.x - edge.x, 2.0 * center.y - edge.y, edge.z); - result.push(make_seg(&far, &edge, &dim_c)); + // The stored points are the two opposite chord points. Their + // midpoint is the measured circle centre. + let (edge, far) = (d.angle_vertex, d.definition_point); + let center = v3( + (edge.x + far.x) * 0.5, + (edge.y + far.y) * 0.5, + (edge.z + far.z) * 0.5, + ); let len = ((edge.x - far.x).powi(2) + (edge.y - far.y).powi(2)) .sqrt() .max(1e-12); let (ux, uy) = ((edge.x - far.x) / len, (edge.y - far.y) / len); - result.extend(dim_terminator(edge, -ux, -uy, &met.arrow1, &dim_c)); - result.extend(dim_terminator(far, ux, uy, &met.arrow2, &dim_c)); - // Optional leader past the near edge toward the text. DIM-DIA-LEADER. - if d.leader_length.abs() > 1e-9 { - let anchor = dim_text_anchor(base, center, edge); - let ld = norm2(anchor.x - edge.x, anchor.y - edge.y, ux, uy); + let ticks = met.dimtsz > 1e-9; + let extension = if ticks { met.dimdle } else { 0.0 }; + let edge_outer = v3( + edge.x + ux * extension, + edge.y + uy * extension, + edge.z, + ); + let far_outer = v3( + far.x - ux * extension, + far.y - uy * extension, + far.z, + ); + if !met.dimsd1 { + result.push(make_seg(&edge_outer, ¢er, &dim_c)); + } + if !met.dimsd2 { + result.push(make_seg(¢er, &far_outer, &dim_c)); + } + let outside = !ticks && met.dimasz > 1e-6 && len < 2.0 * met.dimasz; + if outside { + result.extend(dim_terminator(edge, ux, uy, &met.arrow1, &dim_c)); + result.extend(dim_terminator(far, -ux, -uy, &met.arrow2, &dim_c)); + if !met.dimsoxd { + let stub = 2.0 * met.dimasz; + if !met.dimsd1 { + result.push(make_seg( + &edge, + &v3(edge.x + ux * stub, edge.y + uy * stub, edge.z), + &dim_c, + )); + } + if !met.dimsd2 { + result.push(make_seg( + &far, + &v3(far.x - ux * stub, far.y - uy * stub, far.z), + &dim_c, + )); + } + } + } else { + result.extend(dim_terminator(edge, -ux, -uy, &met.arrow1, &dim_c)); + result.extend(dim_terminator(far, ux, uy, &met.arrow2, &dim_c)); + } + let anchor = dim_text_anchor(base, center, edge); + let distance_squared = |first: Vector3, second: Vector3| { + (first.x - second.x).powi(2) + + (first.y - second.y).powi(2) + + (first.z - second.z).powi(2) + }; + let (leader_tip, suppressed, fallback) = if distance_squared(anchor, edge) + <= distance_squared(anchor, far) + { + (edge, met.dimsd1, (ux, uy)) + } else { + (far, met.dimsd2, (-ux, -uy)) + }; + if !suppressed && d.leader_length.abs() > 1e-9 { + let ld = norm2( + anchor.x - leader_tip.x, + anchor.y - leader_tip.y, + fallback.0, + fallback.1, + ); result.push(make_seg( - &edge, - &v3(edge.x + ld.0 * d.leader_length, edge.y + ld.1 * d.leader_length, edge.z), + &leader_tip, + &v3( + leader_tip.x + ld.0 * d.leader_length.abs(), + leader_tip.y + ld.1 * d.leader_length.abs(), + leader_tip.z, + ), &dim_c, )); } + if !met.dimse1 { + if let Some(points) = crate::scene::dimension_assoc::radial_extension_points( + doc, + base.common.handle, + met.dimexo, + met.dimexe, + ) { + for pair in points.windows(2) { + result.push(make_seg(&pair[0], &pair[1], &ext_c)); + } + } + } result.extend(dim_center_mark(center, met.dimcen, len * 0.5, &dim_c)); } Dimension::Angular2Ln(d) => { @@ -1567,15 +1707,16 @@ mod tests { } // A diameter dimension bakes a line edge-to-edge THROUGH the centre, not a - // radius-length line. The two extreme endpoints must be equidistant from the - // centre (angle_vertex) and the centre must lie between them. + // radius-length line. The two stored extreme endpoints must be equidistant + // from their midpoint and that midpoint must be the circle centre. #[test] fn diameter_dim_bakes_through_center() { use acadrust::entities::DimensionDiameter; let mut doc = CadDocument::new(); let center = Vector3::new(3.0, 4.0, 0.0); let edge = Vector3::new(8.0, 4.0, 0.0); // radius 5 along +x - let mut d = DimensionDiameter::new(center, edge); + let far = Vector3::new(-2.0, 4.0, 0.0); + let mut d = DimensionDiameter::new(edge, far); d.base.text_middle_point = Vector3::new(3.0, 9.0, 0.0); let handle = doc .add_entity(EntityType::Dimension(Dimension::Diameter(d)))