One tool window for sketch Fillet and the three sketch Chamfers (#789)
Sketch Fillet and the three sketch Chamfers share one tool window, with its own icons, labels and a scenario.
This commit is contained in:
1 parent
dbfb689f6c
commit
bdcfe3ff1d
13 files changed
+567
-70
No files matched your search
@@ -357,7 +357,6 @@ fn mode(id: &str) -> Option<Mode> {
|
||||
"sketch.text" => Mode::Points(1),
|
||||
"sketch.edit_text" => Mode::Entities(1),
|
||||
"sketch.blend_curve" => Mode::Points(2),
|
||||
"sketch.fillet" | "sketch.chamfer.equal_distance" | "sketch.chamfer.distance_angle" | "sketch.chamfer.two_distance" => Mode::Entities(1),
|
||||
"sketch.constraint.curvature" | "sketch.circle.two_tangent" => Mode::Entities(2),
|
||||
"sketch.circle.three_tangent" => Mode::Entities(3),
|
||||
"sketch.constrainer" | "sketch.constraint.polygon" => Mode::Entities(0),
|
||||
@@ -414,10 +413,6 @@ pub fn hint(id: &str) -> Option<String> {
|
||||
"sketch.text" => "Text: click where the text starts",
|
||||
"sketch.edit_text" => "Edit Text: click a letter interior or outline",
|
||||
"sketch.blend_curve" => "Blend curve: click the ends of two curves",
|
||||
"sketch.fillet" => "Fillet: click the corner of two lines",
|
||||
"sketch.chamfer.equal_distance" | "sketch.chamfer.distance_angle" | "sketch.chamfer.two_distance" => {
|
||||
"Chamfer: click the corner of two lines"
|
||||
}
|
||||
"sketch.constraint.curvature" => "Curvature: click two curves that share an end",
|
||||
"sketch.circle.two_tangent" => "2-tangent circle: click two curves (the circle goes near the second click)",
|
||||
"sketch.circle.three_tangent" => "3-tangent circle: click three curves",
|
||||
@@ -464,9 +459,30 @@ fn sketch_entity(app: &SolveApp, hits: &[Hit]) -> Option<(String, bool)> {
|
||||
})
|
||||
}
|
||||
|
||||
/// The two editable curves that meet at sketch point `pi`, in curve order, which is the order
|
||||
/// the corner commands resolve them in from a `point` parameter. None unless exactly two meet
|
||||
/// there and each is one the command can work on: a line always, an arc only for a fillet.
|
||||
pub(crate) fn corner_curves(sk: &solidcraft_engine::sketch::Sketch, pi: usize, arcs_ok: bool) -> Option<(usize, usize)> {
|
||||
use solidcraft_engine::sketch::CurveKind;
|
||||
let curves: Vec<_> = sk
|
||||
.curves
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter(|(ci, c)| !sk.is_linked_curve(*ci) && c.kind.ends().is_some_and(|(a, b)| a == pi || b == pi))
|
||||
.take(3)
|
||||
.collect();
|
||||
if curves.iter().any(|(_, c)| !matches!(c.kind, CurveKind::Line { .. }) && !(arcs_ok && matches!(c.kind, CurveKind::Arc { .. }))) {
|
||||
return None;
|
||||
}
|
||||
match curves[..] {
|
||||
[(a, _), (b, _)] => Some((a, b)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Corner tools accept endpoints shared by two editable curves. Pick among those endpoints
|
||||
/// directly so the origin, a circle centre or an overlapping loose point cannot hide a corner.
|
||||
pub(super) fn corner_point(app: &SolveApp, proj: &Proj, pos: Pos2, cmd: &str) -> Option<(Vec2, String)> {
|
||||
pub(crate) fn corner_point(app: &SolveApp, proj: &Proj, pos: Pos2, arcs_ok: bool) -> Option<(Vec2, String)> {
|
||||
let st = app.session.world_state();
|
||||
let ss = st.sketch(active_sketch(app)?)?;
|
||||
let sk = &ss.sketch;
|
||||
@@ -478,21 +494,7 @@ pub(super) fn corner_point(app: &SolveApp, proj: &Proj, pos: Pos2, cmd: &str) ->
|
||||
if distance >= 8.0 {
|
||||
return None;
|
||||
}
|
||||
let curves: Vec<_> = sk
|
||||
.curves
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter(|(ci, c)| !sk.is_linked_curve(*ci) && c.kind.ends().is_some_and(|(a, b)| a == pi || b == pi))
|
||||
.take(3)
|
||||
.collect();
|
||||
if curves.len() != 2
|
||||
|| curves.iter().any(|(_, c)| {
|
||||
!matches!(c.kind, solidcraft_engine::sketch::CurveKind::Line { .. })
|
||||
&& (cmd != "sketch.fillet" || !matches!(c.kind, solidcraft_engine::sketch::CurveKind::Arc { .. }))
|
||||
})
|
||||
{
|
||||
return None;
|
||||
}
|
||||
corner_curves(sk, pi, arcs_ok)?;
|
||||
Some((distance, point.pos, point.id.clone()))
|
||||
})
|
||||
.min_by(|a, b| a.0.total_cmp(&b.0))
|
||||
@@ -517,21 +519,6 @@ fn curve_len(app: &SolveApp, id: &str) -> f64 {
|
||||
ss.sketch.curve_index(id).map(|c| ss.sketch.polyline(c).windows(2).map(|w| w[0].dist(w[1])).sum::<f64>()).unwrap_or(10.0)
|
||||
}
|
||||
|
||||
/// Lines meeting at a sketch point.
|
||||
fn corner_len(app: &SolveApp, point: &str) -> f64 {
|
||||
let st = app.session.world_state();
|
||||
let Some(ss) = active_sketch(app).and_then(|s| st.sketch(s)) else { return 10.0 };
|
||||
let sk = &ss.sketch;
|
||||
let Some(q) = sk.resolve_point(point) else { return 10.0 };
|
||||
sk.curves
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter(|(_, c)| c.kind.uses(q) && matches!(c.kind, solidcraft_engine::sketch::CurveKind::Line { .. }))
|
||||
.map(|(i, _)| sk.polyline(i).windows(2).map(|w| w[0].dist(w[1])).sum::<f64>())
|
||||
.fold(f64::INFINITY, f64::min)
|
||||
.min(1e6)
|
||||
}
|
||||
|
||||
fn round_nice(x: f64) -> f64 {
|
||||
if !(x.is_finite() && x > 0.0) {
|
||||
return 1.0;
|
||||
@@ -700,12 +687,6 @@ pub fn on_click(app: &mut SolveApp, tool: &mut Tool, proj: &Proj, pos: Pos2) {
|
||||
place_point(app, tool, p);
|
||||
}
|
||||
Mode::Entities(n) => {
|
||||
if cmd == "sketch.fillet" || cmd.starts_with("sketch.chamfer.") {
|
||||
if let Some((_, id)) = corner_point(app, proj, pos, cmd) {
|
||||
run_corner(app, cmd, &id);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if cmd == "sketch.edit_text" {
|
||||
let selection = hits.first().and_then(|hit| match hit {
|
||||
Hit::SketchCurve { sketch, id, .. } if Some(*sketch) == active_sketch(app) => {
|
||||
@@ -863,21 +844,6 @@ fn run_points(app: &mut SolveApp, t: &Tool) {
|
||||
let _ = app.run(t.cmd, params);
|
||||
}
|
||||
|
||||
fn run_corner(app: &mut SolveApp, cmd: &str, point: &str) {
|
||||
let size = round_nice(corner_len(app, point) * 0.2);
|
||||
let params = match cmd {
|
||||
"sketch.fillet" => json!({"point": point, "radius": size}),
|
||||
"sketch.chamfer.distance_angle" => json!({"point": point, "distance": size, "angle": 45}),
|
||||
"sketch.chamfer.two_distance" => json!({"point": point, "distance": size, "distance2": size}),
|
||||
_ => json!({"point": point, "distance": size}),
|
||||
};
|
||||
if let Ok(v) = app.run(cmd, params)
|
||||
&& let Some(p) = v["param"].as_str()
|
||||
{
|
||||
app.dialog = Some(crate::dialogs::Dialog::edit_param(&app.session, p));
|
||||
}
|
||||
}
|
||||
|
||||
fn run_entities(app: &mut SolveApp, t: &Tool) {
|
||||
let k = &t.picks;
|
||||
let params = match t.cmd {
|
||||
|
||||
Reference in new issue
Block a user