forked from 1b-agent/opencadstudio-upstream
feat(commands): expand standard CAD command coverage
Integrate a large batch of standard CAD commands and fix several name/behaviour mismatches, with no product references in code. 3D solids (reusing the truck B-rep pipeline): - SLICE, INTERFERE, PRESSPULL, POLYSOLID, PYRAMID, SECTION - 3DROTATE, 3DMIRROR, 3DALIGN (cached-solid transforms) Annotation / text: - ARCTEXT, SPLINEFIT (Catmull-Rom to Bezier), DIMJOGGED, OBJECTSCALE (XData markers honoured by the existing geometry-gen / tessellator) Blocks / misc: - NCOPY (block-content extraction via explode_entity) - OPTIONS, SYNCPVIEWPORTS, THICKEN, plus earlier toggles, aliases, system variables, and layer/style/view commands POINTCLOUD/RECAP and UNDERLAYLAYERS/UOSNAP are intentionally left out: they require a proprietary binary / PDF-layer parser, a GPU point renderer, and real test files. Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
1 parent
76ef544cda
commit
c19c18c2f2
24 files changed
+4405
-216
No files matched your search
+75
-24
@@ -805,7 +805,11 @@ impl Grippable for Dimension {
|
||||
}
|
||||
}
|
||||
|
||||
fn apply_grip_menu(&mut self, grip_id: usize, action: crate::scene::model::object::GripMenuAction) {
|
||||
fn apply_grip_menu(
|
||||
&mut self,
|
||||
grip_id: usize,
|
||||
action: crate::scene::model::object::GripMenuAction,
|
||||
) {
|
||||
use crate::scene::model::object::GripMenuAction as A;
|
||||
let (_dim_line_grip, text_grip) = match self {
|
||||
Dimension::Linear(_) | Dimension::Aligned(_) => (2, 3),
|
||||
@@ -1035,9 +1039,7 @@ fn tessellate_dimension_inner(
|
||||
// draws 2D fills under all wires, so the line is gapped rather than masked.
|
||||
let dimgap_local = style.map(|s| (s.dimgap * dim_scale) as f32).unwrap_or(0.09);
|
||||
let text_break = {
|
||||
let tp = vec3_local(
|
||||
dimension_text_pos_f64(dim, style, dim_txt, dim_scale),
|
||||
);
|
||||
let tp = vec3_local(dimension_text_pos_f64(dim, style, dim_txt, dim_scale));
|
||||
let tw = dimension_text_value(dim, style)
|
||||
.map(|t| t.chars().count() as f32 * dim_txt as f32 * 0.6)
|
||||
.unwrap_or(0.0);
|
||||
@@ -1576,7 +1578,29 @@ fn dimension_geometry(
|
||||
let center = lv(d.angle_vertex);
|
||||
let point = lv(d.definition_point);
|
||||
let text = dimension_text_position(dim);
|
||||
add_segment(&mut g.dim_lines, center, point);
|
||||
// A jogged radius dim (marked via XData) replaces the straight radial
|
||||
// leader with a foreshortened zig-zag at ~45° near its midpoint.
|
||||
let jogged = dim
|
||||
.base()
|
||||
.common
|
||||
.extended_data
|
||||
.get_record("OCS_JOGGED")
|
||||
.is_some();
|
||||
if jogged {
|
||||
let delta = point - center;
|
||||
let dist = delta.length();
|
||||
let u = normalized_or(delta, Vec3::X);
|
||||
let perp = Vec3::new(-u.y, u.x, 0.0);
|
||||
let half = (dist * 0.06).max(1e-3);
|
||||
let mid = center + u * (dist * 0.5);
|
||||
let a = mid - u * half + perp * half;
|
||||
let b = mid + u * half - perp * half;
|
||||
add_segment(&mut g.dim_lines, center, a);
|
||||
add_segment(&mut g.dim_lines, a, b);
|
||||
add_segment(&mut g.dim_lines, b, point);
|
||||
} else {
|
||||
add_segment(&mut g.dim_lines, center, point);
|
||||
}
|
||||
// Honour leader_length: extend from the arrow tip past it
|
||||
// toward the text by that distance along (text - point).
|
||||
let leader_dir = normalized_or(text - point, Vec3::X);
|
||||
@@ -1877,13 +1901,7 @@ fn append_angular_dimension(
|
||||
}
|
||||
|
||||
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);
|
||||
match dim {
|
||||
Dimension::Linear(d) => vec![
|
||||
@@ -2831,9 +2849,17 @@ pub(crate) fn baked_dimension_text_entity(
|
||||
|| (style_name.trim().is_empty() && s.name.eq_ignore_ascii_case("Standard"))
|
||||
});
|
||||
let dim_scale = style
|
||||
.map(|s| if s.dimscale > 1e-6 { s.dimscale } else { anno_scale })
|
||||
.map(|s| {
|
||||
if s.dimscale > 1e-6 {
|
||||
s.dimscale
|
||||
} else {
|
||||
anno_scale
|
||||
}
|
||||
})
|
||||
.unwrap_or(1.0);
|
||||
let dim_txt = style.map(|s| s.dimtxt * dim_scale).unwrap_or(2.5 * dim_scale);
|
||||
let dim_txt = style
|
||||
.map(|s| s.dimtxt * dim_scale)
|
||||
.unwrap_or(2.5 * dim_scale);
|
||||
let mut ent = dimension_text_entity(dim, dim_txt, style, document, dim_scale)?;
|
||||
// For a non-default-aligned Text, pin the DXF alignment point (group 11) to
|
||||
// the insertion point so other CAD programs anchor the centred text where
|
||||
@@ -2859,14 +2885,11 @@ mod dimtad_tests {
|
||||
fn above_is_up_regardless_of_direction() {
|
||||
let (first, second, defpt) = (v(0.0, 10.0), v(20.0, 10.0), v(0.0, 0.0));
|
||||
let perp = 5.0;
|
||||
let fwd =
|
||||
text_on_dim_line(first, second, defpt, 1.0, 0.0, 0, perp, 0.0, 1.0, false, 1);
|
||||
let rev =
|
||||
text_on_dim_line(first, second, defpt, -1.0, 0.0, 0, perp, 0.0, 1.0, false, 1);
|
||||
let fwd = text_on_dim_line(first, second, defpt, 1.0, 0.0, 0, perp, 0.0, 1.0, false, 1);
|
||||
let rev = text_on_dim_line(first, second, defpt, -1.0, 0.0, 0, perp, 0.0, 1.0, false, 1);
|
||||
assert!(fwd.y > 0.0, "above must be +Y, got {}", fwd.y);
|
||||
assert!(rev.y > 0.0, "above must be +Y even reversed, got {}", rev.y);
|
||||
let below =
|
||||
text_on_dim_line(first, second, defpt, 1.0, 0.0, 0, perp, 0.0, 1.0, false, 4);
|
||||
let below = text_on_dim_line(first, second, defpt, 1.0, 0.0, 0, perp, 0.0, 1.0, false, 4);
|
||||
assert!(below.y < 0.0, "below must be -Y, got {}", below.y);
|
||||
}
|
||||
|
||||
@@ -2877,13 +2900,41 @@ mod dimtad_tests {
|
||||
let perp = 5.0;
|
||||
// Object at y=0, dim line above it (y=10): away → further above.
|
||||
let above = text_on_dim_line(
|
||||
v(0.0, 0.0), v(20.0, 0.0), v(0.0, 10.0), 1.0, 0.0, 0, perp, 0.0, 1.0, false, 2,
|
||||
v(0.0, 0.0),
|
||||
v(20.0, 0.0),
|
||||
v(0.0, 10.0),
|
||||
1.0,
|
||||
0.0,
|
||||
0,
|
||||
perp,
|
||||
0.0,
|
||||
1.0,
|
||||
false,
|
||||
2,
|
||||
);
|
||||
assert!(
|
||||
above.y > 10.0,
|
||||
"outside must clear the object side, got {}",
|
||||
above.y
|
||||
);
|
||||
assert!(above.y > 10.0, "outside must clear the object side, got {}", above.y);
|
||||
// Object at y=0, dim line below it (y=-10): away → further below.
|
||||
let below = text_on_dim_line(
|
||||
v(0.0, 0.0), v(20.0, 0.0), v(0.0, -10.0), 1.0, 0.0, 0, perp, 0.0, 1.0, false, 2,
|
||||
v(0.0, 0.0),
|
||||
v(20.0, 0.0),
|
||||
v(0.0, -10.0),
|
||||
1.0,
|
||||
0.0,
|
||||
0,
|
||||
perp,
|
||||
0.0,
|
||||
1.0,
|
||||
false,
|
||||
2,
|
||||
);
|
||||
assert!(
|
||||
below.y < -10.0,
|
||||
"outside must clear the object side, got {}",
|
||||
below.y
|
||||
);
|
||||
assert!(below.y < -10.0, "outside must clear the object side, got {}", below.y);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user