Two-entity constraints move only the second pick (tangent, parallel, perpendicular, equal, concentric, coincident, collinear, symmetric, midpoint): the constraint is applied with the first entity held (solve_holding), the second keeping its size where it can (lines turn and slide, circles translate), then resizing; if the second is fixed, projected or fully constrained the first moves instead, and if neither can the constraint is refused and nothing changes; later solves hold nothing. Context-menu constraints keep the selection order; a curve picked before a point puts the point on the curve
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
3e7826fe56
commit
7f9a8f2afd
5 files changed
+339
-12
No files matched your search
@@ -61,8 +61,20 @@ struct Layout {
|
||||
n: usize,
|
||||
}
|
||||
|
||||
fn layout(sk: &Sketch) -> Layout {
|
||||
/// Geometry held in place for one solve: point indices and curves whose radius is held.
|
||||
#[derive(Clone, Debug, Default, PartialEq)]
|
||||
pub struct Hold {
|
||||
pub points: Vec<usize>,
|
||||
pub radii: Vec<usize>,
|
||||
}
|
||||
|
||||
fn layout(sk: &Sketch, hold: &Hold) -> Layout {
|
||||
let mut fixed: Vec<bool> = sk.points.iter().map(|p| p.fixed).collect();
|
||||
for p in &hold.points {
|
||||
if let Some(f) = fixed.get_mut(*p) {
|
||||
*f = true;
|
||||
}
|
||||
}
|
||||
for c in &sk.constraints {
|
||||
if let ConstraintKind::Fix { p } = c.kind
|
||||
&& let Some(f) = fixed.get_mut(p)
|
||||
@@ -92,8 +104,9 @@ fn layout(sk: &Sketch) -> Layout {
|
||||
let rvar = sk
|
||||
.curves
|
||||
.iter()
|
||||
.map(|c| match c.kind {
|
||||
CurveKind::Circle { .. } | CurveKind::Ellipse { .. } if c.link.is_none() && !c.fixed => {
|
||||
.enumerate()
|
||||
.map(|(i, c)| match c.kind {
|
||||
CurveKind::Circle { .. } | CurveKind::Ellipse { .. } if c.link.is_none() && !c.fixed && !hold.radii.contains(&i) => {
|
||||
n += 1;
|
||||
Some(n - 1)
|
||||
}
|
||||
@@ -774,7 +787,14 @@ fn lm(sk: &Sketch, lay: &Layout, blocks: &[(Block, Vec<usize>)], vars: &[usize],
|
||||
/// Solve the sketch in place. On failure the geometry is restored and the report lists the
|
||||
/// violated constraints.
|
||||
pub fn solve(sk: &mut Sketch) -> SolveReport {
|
||||
let lay = layout(sk);
|
||||
solve_holding(sk, &Hold::default())
|
||||
}
|
||||
|
||||
/// Solve with some geometry held as if it were fixed (for this solve only): applying a
|
||||
/// constraint between two entities holds the first so only the second moves. Everything else
|
||||
/// moves as little as it can. On failure the geometry is restored.
|
||||
pub fn solve_holding(sk: &mut Sketch, hold: &Hold) -> SolveReport {
|
||||
let lay = layout(sk, hold);
|
||||
let mut x = vec![0.0; lay.n];
|
||||
for (i, p) in sk.points.iter().enumerate() {
|
||||
if let Some(v) = lay.pvar.get(i).copied().flatten() {
|
||||
|
||||
Reference in new issue
Block a user