Thanks @erkexzcx.
This commit is contained in:
1 parent
daf618c344
commit
a422fb1a4b
10 files changed
+120
-14
No files matched your search
@@ -136,6 +136,11 @@ fn map_plane(m: &Mat, p: &Plane) -> Plane {
|
||||
fn map_plane_ref(m: &Mat, p: &mut PlaneRef) {
|
||||
match p {
|
||||
PlaneRef::Custom { plane } => *plane = map_plane(m, plane),
|
||||
PlaneRef::Placed { origin, x_dir, y_dir } => {
|
||||
map_point_expr(m, origin);
|
||||
*x_dir = apply_vector(m, *x_dir);
|
||||
*y_dir = apply_vector(m, *y_dir);
|
||||
}
|
||||
PlaneRef::Face { plane, at, .. } => {
|
||||
*plane = map_plane(m, plane);
|
||||
*at = apply_point(m, *at);
|
||||
|
||||
@@ -223,7 +223,7 @@ impl crate::Feature {
|
||||
for (_, e, _) in self.kind.inputs_mut() {
|
||||
*e = clone_expression(e, parameters);
|
||||
}
|
||||
for e in self.kind.point_expr_mut().into_iter().flatten() {
|
||||
for e in self.kind.placement_exprs_mut() {
|
||||
*e = clone_expression(e, parameters);
|
||||
}
|
||||
self.kind.remap_bodies(bodies);
|
||||
|
||||
@@ -42,6 +42,14 @@ pub enum PlaneRef {
|
||||
Origin { name: String },
|
||||
/// An explicit plane (e.g. picked from a planar face).
|
||||
Custom { plane: Plane },
|
||||
/// An explicit plane whose origin is given as length expressions
|
||||
/// (`{origin: ["half", 0, 0], normal: [1, 0, 0]}`), so it follows parameter changes.
|
||||
Placed {
|
||||
#[serde(with = "point_expr")]
|
||||
origin: PointExpr,
|
||||
x_dir: Vec3,
|
||||
y_dir: Vec3,
|
||||
},
|
||||
/// Another plane offset along its normal by an expression.
|
||||
Offset { base: Box<PlaneRef>, distance: String },
|
||||
/// Another plane rotated about a line (in world coordinates) by an angle expression.
|
||||
@@ -2938,6 +2946,15 @@ impl Document {
|
||||
PlaneRef::Custom { plane } | PlaneRef::Face { plane, .. } => {
|
||||
Plane::new(plane.origin, plane.x, plane.y).ok_or_else(|| DocError::Invalid("degenerate plane".into()))
|
||||
}
|
||||
PlaneRef::Placed { origin, x_dir, y_dir } => {
|
||||
let [x, y, z] = origin;
|
||||
let o =
|
||||
Vec3::new(Self::eval_in(vals, x, Kind::Length)?, Self::eval_in(vals, y, Kind::Length)?, Self::eval_in(vals, z, Kind::Length)?);
|
||||
if ![o.x, o.y, o.z].iter().all(|c| c.is_finite() && c.abs() < 1e9) {
|
||||
return Err(DocError::Invalid("the plane's origin is out of range".into()));
|
||||
}
|
||||
Plane::new(o, *x_dir, *y_dir).ok_or_else(|| DocError::Invalid("degenerate plane".into()))
|
||||
}
|
||||
PlaneRef::Offset { base, distance } => {
|
||||
let b = self.resolve_plane_in(vals, base, depth + 1, st)?;
|
||||
Ok(b.offset(Self::eval_in(vals, distance, Kind::Length)?))
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
//! An explicit plane (a mirror's, or any plane reference) can be `placed`: an `origin` of three
|
||||
//! length expressions with `x_dir` and `y_dir`, so it follows the design's parameters (#1492). A
|
||||
//! plane whose origin is plain numbers is still saved as `custom`. Older designs need no
|
||||
//! transformation; 0.13.x asks for an update instead of failing to read the plane.
|
||||
@@ -44,6 +44,30 @@ impl FeatureKind {
|
||||
v
|
||||
}
|
||||
|
||||
/// The coordinates of the points that place the feature: a primitive's position, an
|
||||
/// explicit plane's origin. They are not inputs (no parameter names), but follow
|
||||
/// parameters as inputs do.
|
||||
pub fn placement_exprs_mut(&mut self) -> Vec<&mut String> {
|
||||
let mut v = Vec::new();
|
||||
self.walk_exprs_mut(&mut |(_, e, _, role)| {
|
||||
if role == ExprRole::Placement {
|
||||
v.push(e);
|
||||
}
|
||||
});
|
||||
v
|
||||
}
|
||||
|
||||
/// Read-only view of [`FeatureKind::placement_exprs_mut`].
|
||||
pub fn placement_exprs(&self) -> Vec<&str> {
|
||||
let mut v = Vec::new();
|
||||
self.walk_exprs(&mut |(_, e, _, role)| {
|
||||
if role == ExprRole::Placement {
|
||||
v.push(e.as_str());
|
||||
}
|
||||
});
|
||||
v
|
||||
}
|
||||
|
||||
/// Every expression the feature uses: its inputs, then a primitive's placement coordinates.
|
||||
pub fn expressions(&self) -> Vec<&str> {
|
||||
let (mut inputs, mut placement) = (Vec::new(), Vec::new());
|
||||
@@ -575,7 +599,7 @@ impl Document {
|
||||
}
|
||||
}
|
||||
}
|
||||
if f.kind.point_expr().is_some_and(|p| p.iter().any(|e| expr::references(e).iter().any(|r| r == name))) {
|
||||
if f.kind.placement_exprs().iter().any(|e| expr::references(e).iter().any(|r| r == name)) {
|
||||
out.push(ParamUser::Feature { feature: f.id, name: f.name.clone(), input: "Position".into() });
|
||||
}
|
||||
if let FeatureKind::Sketch { sketch, .. } = &f.kind {
|
||||
@@ -646,7 +670,7 @@ impl Document {
|
||||
*x = new.to_string();
|
||||
}
|
||||
}
|
||||
for e in f.kind.point_expr_mut().into_iter().flatten() {
|
||||
for e in f.kind.placement_exprs_mut() {
|
||||
let r = expr::rename_reference(e, old, new);
|
||||
if r != *e {
|
||||
*e = r;
|
||||
|
||||
+15
-2
@@ -264,8 +264,9 @@ impl<F: Fn(usize, usize) -> &'static str> Label for F {
|
||||
}
|
||||
}
|
||||
|
||||
/// The offsets and angles of a plane, outermost first (nesting is capped like every walk over a
|
||||
/// plane), the construction plane it is built on, and the plane itself.
|
||||
/// The offsets and angles of a plane, outermost first, and an explicit origin's coordinates
|
||||
/// (nesting is capped like every walk over a plane), the construction plane it is built on, and
|
||||
/// the plane itself.
|
||||
impl Walk for PlaneRef {
|
||||
fn walk_exprs<'a>(&'a self, f: &mut dyn FnMut(ExprItem<'a>)) {
|
||||
let mut p = self;
|
||||
@@ -280,6 +281,12 @@ impl Walk for PlaneRef {
|
||||
p = base;
|
||||
}
|
||||
PlaneRef::AlongPath { t, .. } => return f(("Distance (0 to 1)", t, Kind::Unitless, ExprRole::Input)),
|
||||
PlaneRef::Placed { origin, .. } => {
|
||||
for (label, e) in ["X", "Y", "Z"].into_iter().zip(origin) {
|
||||
f((label, e, Kind::Length, ExprRole::Placement));
|
||||
}
|
||||
return;
|
||||
}
|
||||
_ => return,
|
||||
}
|
||||
}
|
||||
@@ -297,6 +304,12 @@ impl Walk for PlaneRef {
|
||||
p = base;
|
||||
}
|
||||
PlaneRef::AlongPath { t, .. } => return f(("Distance (0 to 1)", t, Kind::Unitless, ExprRole::Input)),
|
||||
PlaneRef::Placed { origin, .. } => {
|
||||
for (label, e) in ["X", "Y", "Z"].into_iter().zip(origin) {
|
||||
f((label, e, Kind::Length, ExprRole::Placement));
|
||||
}
|
||||
return;
|
||||
}
|
||||
_ => return,
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user