Fix/Unfix on every sketch entity: points (Fix constraint) and lines, arcs, circles, ellipses, splines and conics (fixed curves hold their points and radius); ConstraintFix takes entities (fixes them all unless all are fixed); the toolbar button and the context menu act on the whole selection; fixed points never move when dragged or solved; projected geometry counts as fixed; fixed geometry is drawn green; sketch.inspect reports fixed
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AS5Tn3xieewUSg3uxrMVdL
This commit is contained in:
1 parent
b457b6b7b6
commit
5b8816aa7d
11 files changed
+252
-35
No files matched your search
@@ -407,7 +407,15 @@ impl Sketch {
|
||||
}
|
||||
};
|
||||
let cid = self.fresh(prefix);
|
||||
self.curves.push(Curve { id: cid, kind, construction: false, reversed: false, link: Some(id.to_string()), centerline: false });
|
||||
self.curves.push(Curve {
|
||||
id: cid,
|
||||
kind,
|
||||
construction: false,
|
||||
reversed: false,
|
||||
link: Some(id.to_string()),
|
||||
centerline: false,
|
||||
fixed: false,
|
||||
});
|
||||
}
|
||||
for li in &lay.lone {
|
||||
point(self, *li)?;
|
||||
|
||||
@@ -140,6 +140,9 @@ pub struct Curve {
|
||||
/// an axis (revolve, diameter dimensions).
|
||||
#[serde(default, skip_serializing_if = "std::ops::Not::not")]
|
||||
pub centerline: bool,
|
||||
/// Fixed (locked): its points and radius are constants for the solver.
|
||||
#[serde(default, skip_serializing_if = "std::ops::Not::not")]
|
||||
pub fixed: bool,
|
||||
}
|
||||
|
||||
/// Geometric constraints and dimensions. Indices refer to `Sketch::points` (`p`, `q`) or
|
||||
@@ -536,7 +539,15 @@ impl Sketch {
|
||||
return Err(SketchError::Invalid("line needs two distinct points".into()));
|
||||
}
|
||||
let id = self.curve_id(id, "l")?;
|
||||
self.curves.push(Curve { id, kind: CurveKind::Line { a, b }, construction: false, reversed: false, link: None, centerline: false });
|
||||
self.curves.push(Curve {
|
||||
id,
|
||||
kind: CurveKind::Line { a, b },
|
||||
construction: false,
|
||||
reversed: false,
|
||||
link: None,
|
||||
centerline: false,
|
||||
fixed: false,
|
||||
});
|
||||
Ok(self.curves.len() - 1)
|
||||
}
|
||||
|
||||
@@ -565,7 +576,15 @@ impl Sketch {
|
||||
Some(i) if i < self.points.len() => i,
|
||||
_ => self.own_point(&id, "center", center)?,
|
||||
};
|
||||
self.curves.push(Curve { id, kind: CurveKind::Circle { c, r }, construction: false, reversed: false, link: None, centerline: false });
|
||||
self.curves.push(Curve {
|
||||
id,
|
||||
kind: CurveKind::Circle { c, r },
|
||||
construction: false,
|
||||
reversed: false,
|
||||
link: None,
|
||||
centerline: false,
|
||||
fixed: false,
|
||||
});
|
||||
Ok(self.curves.len() - 1)
|
||||
}
|
||||
|
||||
@@ -591,7 +610,15 @@ impl Sketch {
|
||||
Some(i) if i < n && i != a => i,
|
||||
_ => self.own_point(&id, "end", p1)?,
|
||||
};
|
||||
self.curves.push(Curve { id, kind: CurveKind::Arc { c, a, b }, construction: false, reversed: false, link: None, centerline: false });
|
||||
self.curves.push(Curve {
|
||||
id,
|
||||
kind: CurveKind::Arc { c, a, b },
|
||||
construction: false,
|
||||
reversed: false,
|
||||
link: None,
|
||||
centerline: false,
|
||||
fixed: false,
|
||||
});
|
||||
Ok(self.curves.len() - 1)
|
||||
}
|
||||
|
||||
@@ -680,6 +707,40 @@ impl Sketch {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Is point `i` held in place: fixed, projected (linked), fixed by a Fix constraint or a
|
||||
/// point of a fixed curve.
|
||||
pub fn point_locked(&self, i: usize) -> bool {
|
||||
self.points.get(i).is_some_and(|p| p.fixed || p.link.is_some())
|
||||
|| self.constraints.iter().any(|c| c.kind == ConstraintKind::Fix { p: i })
|
||||
|| self.curves.iter().any(|c| c.fixed && c.kind.uses(i))
|
||||
}
|
||||
|
||||
/// [`Sketch::point_locked`] for every point at once.
|
||||
pub fn locked_points(&self) -> Vec<bool> {
|
||||
let mut out: Vec<bool> = self.points.iter().map(|p| p.fixed || p.link.is_some()).collect();
|
||||
let mut set = |i: usize| {
|
||||
if let Some(x) = out.get_mut(i) {
|
||||
*x = true;
|
||||
}
|
||||
};
|
||||
for c in &self.constraints {
|
||||
if let ConstraintKind::Fix { p } = c.kind {
|
||||
set(p);
|
||||
}
|
||||
}
|
||||
for c in self.curves.iter().filter(|c| c.fixed) {
|
||||
for p in c.kind.point_ids() {
|
||||
set(p);
|
||||
}
|
||||
}
|
||||
out
|
||||
}
|
||||
|
||||
/// Is curve `c` held in place: fixed or projected (linked).
|
||||
pub fn curve_locked(&self, c: usize) -> bool {
|
||||
self.curves.get(c).is_some_and(|c| c.fixed || c.link.is_some())
|
||||
}
|
||||
|
||||
/// Radius of a circle or arc.
|
||||
pub fn radius(&self, ci: usize) -> Option<f64> {
|
||||
match self.curves.get(ci)?.kind {
|
||||
@@ -834,7 +895,7 @@ impl Sketch {
|
||||
}
|
||||
};
|
||||
let id = self.curve_id(id, prefix)?;
|
||||
self.curves.push(Curve { id, kind, construction: false, reversed: false, link: None, centerline: false });
|
||||
self.curves.push(Curve { id, kind, construction: false, reversed: false, link: None, centerline: false, fixed: false });
|
||||
Ok(self.curves.len() - 1)
|
||||
}
|
||||
|
||||
|
||||
@@ -70,6 +70,13 @@ fn layout(sk: &Sketch) -> Layout {
|
||||
*f = true;
|
||||
}
|
||||
}
|
||||
for c in sk.curves.iter().filter(|c| c.fixed) {
|
||||
for p in c.kind.point_ids() {
|
||||
if let Some(f) = fixed.get_mut(p) {
|
||||
*f = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
let mut n = 0;
|
||||
let pvar = fixed
|
||||
.iter()
|
||||
@@ -86,7 +93,7 @@ fn layout(sk: &Sketch) -> Layout {
|
||||
.curves
|
||||
.iter()
|
||||
.map(|c| match c.kind {
|
||||
CurveKind::Circle { .. } | CurveKind::Ellipse { .. } if c.link.is_none() => {
|
||||
CurveKind::Circle { .. } | CurveKind::Ellipse { .. } if c.link.is_none() && !c.fixed => {
|
||||
n += 1;
|
||||
Some(n - 1)
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user