* Sketch: the first dimension scales a sketch drawn by eye (#1365) Lines drawn by eye have no size of their own until a dimension gives them one, but the first dimension kept every other drawn length and distorted the sketch to fit (a free construction line through the origin turned instead of the shape moving). The dimension tool now scales the whole sketch about its origin to the first length dimension, as long as nothing in the sketch fixes a size yet: no other driving length dimension, nothing fixed, projected or patterned. Every geometric constraint and angle holds on the scaled sketch. Later dimensions size what they measure as before; sketch.dimension does this only with scale_sketch: true, so scripts are unchanged. Fixes #1365 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Scenario s01: dimension the box's height too, now that the first dimension scales the sketch 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
8b7fa2602e
commit
ef53bc46f3
6 files changed
+168
-8
No files matched your search
@@ -949,6 +949,54 @@ impl Sketch {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// The sketch scaled by `factor` about its origin, for its first dimension (#1365): drawn
|
||||
/// geometry has no size of its own until a dimension gives it one, so the first length
|
||||
/// dimension scales the whole sketch to its value instead of distorting it. Only a sketch
|
||||
/// with nothing that fixes a size: no other driving length dimension, nothing fixed,
|
||||
/// projected or patterned, no offsets and no 3D curves. Every geometric constraint
|
||||
/// (coincident, horizontal, parallel, tangent, equal, symmetric, …) and every angle holds
|
||||
/// on the scaled sketch as it held before. `None` when the sketch does not qualify.
|
||||
pub fn scaled_for_first_dimension(&self, factor: f64) -> Option<Sketch> {
|
||||
if !(factor.is_finite() && (1e-6..=1e6).contains(&factor)) {
|
||||
return None;
|
||||
}
|
||||
let sizes = self.constraints.iter().any(|c| match c.kind {
|
||||
ConstraintKind::Fix { .. } | ConstraintKind::PatternPoint { .. } | ConstraintKind::PatternRadius { .. } => true,
|
||||
ref k => k.is_dimension() && !k.is_angle() && !c.driven,
|
||||
});
|
||||
if sizes
|
||||
|| !self.links.is_empty()
|
||||
|| !self.patterns.is_empty()
|
||||
|| !self.offsets.is_empty()
|
||||
|| !self.freeform_offsets.is_empty()
|
||||
|| !self.wires.is_empty()
|
||||
|| self.curves.iter().any(|c| c.fixed || c.link.is_some())
|
||||
|| self.points.iter().enumerate().any(|(i, p)| (p.fixed || p.link.is_some()) && (i != 0 || p.pos != Vec2::ZERO))
|
||||
{
|
||||
return None;
|
||||
}
|
||||
let mut out = self.clone();
|
||||
for p in out.points.iter_mut().filter(|p| !p.fixed) {
|
||||
p.pos = p.pos * factor;
|
||||
if !in_range(p.pos) {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
for c in &mut out.curves {
|
||||
if let CurveKind::Circle { r, .. } | CurveKind::Ellipse { r, .. } = &mut c.kind {
|
||||
*r *= factor;
|
||||
if !radius_in_range(*r) {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Dimension texts keep their places relative to what they measure.
|
||||
for t in out.constraints.iter_mut().filter_map(|c| c.text.as_mut()) {
|
||||
*t = *t * factor;
|
||||
}
|
||||
Some(out)
|
||||
}
|
||||
|
||||
/// 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 {
|
||||
|
||||
Reference in new issue
Block a user