* Smart Extrude: direction from the picked side, Cut into a body stays a Cut (#1257) - A sketch profile (or a thin extrude's curve) extrudes toward the side it was picked from: from the bottom view it goes down. Body faces still go outward. - The automatic operation is latched per side of the profile: a drag that starts into a body is a Cut and stays one past the far side; a Join does not become a Cut when it reaches another body. Passing through zero decides afresh for the new side. - An explicit operation, Direction or Reverse ends the automatic choices. - auto_operation also looks just past the profile, so a long cut through a body reads as a Cut from the start (the engine's operation: "auto" too). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Scenario s07: the XZ profile seen from behind now extrudes toward the camera Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
d73cd8a177
commit
ed22d663e4
8 files changed
+363
-11
No files matched your search
@@ -137,9 +137,16 @@ fn extrude_base(s: &Session, p: &Value) -> Option<(Vec3, Vec3)> {
|
||||
Some((ss.plane.to_world(q), ss.plane.normal()))
|
||||
}
|
||||
|
||||
/// How far past the profile [`auto_operation`] looks for material it starts in.
|
||||
const START_PROBE_MM: f64 = 0.1;
|
||||
|
||||
/// What `operation: "auto"` means for an extrude with these parameters: `cut` when it goes
|
||||
/// into a body, otherwise `join` when the active component has a solid. Keeping an
|
||||
/// addition separate requires an explicit `new` operation.
|
||||
///
|
||||
/// "Goes into a body" is decided where the extrude starts: just past the profile in the
|
||||
/// direction it grows, or halfway along it. With the halfway point alone, a cut dragged far
|
||||
/// past a body's far side read as a Join (#1257).
|
||||
pub fn auto_operation(s: &Session, p: &Value) -> Option<&'static str> {
|
||||
let d = s.doc.eval(&expr(p, "distance")?, Kind::Length).ok()?;
|
||||
let dir = str_(p, "direction").map(str::to_ascii_lowercase);
|
||||
@@ -161,10 +168,13 @@ pub fn auto_operation(s: &Session, p: &Value) -> Option<&'static str> {
|
||||
return Some("new");
|
||||
}
|
||||
let inside = |q: Vec3| bodies.iter().any(|b| b.mesh().contains(q));
|
||||
// A step into whatever is right in front of the profile, short of the far end.
|
||||
let near = |d: f64| d.signum() * (d.abs() * 0.5).min(START_PROBE_MM);
|
||||
let into = |d: f64| inside(base + n * near(d)) || inside(base + n * (d * 0.5));
|
||||
if symmetric {
|
||||
return Some(if inside(base + n * (d.abs() * 0.5)) || inside(base - n * (d.abs() * 0.5)) { "cut" } else { "join" });
|
||||
return Some(if into(d.abs()) || into(-d.abs()) { "cut" } else { "join" });
|
||||
}
|
||||
if inside(base + n * (d * 0.5)) {
|
||||
if into(d) {
|
||||
Some("cut")
|
||||
} else {
|
||||
// A profile can meet material along its side, or only around part of a
|
||||
|
||||
Reference in new issue
Block a user