mirror of
https://github.com/bherbruck/solidcraft.git
synced 2026-11-06 20:02:16 +00:00
Blends: a picked edge is named as the blend takes it, the rim and not the seam
A chamfer picked at (10, 0, 20) on a cylinder's top rim lies on the vertex where SMLib's cylinder has its seam. The blend takes the rim there (blend_smlib::resolve: a seam or a smooth join loses a tie), but the name stored with the feature came from the nearest mesh edge, the seam (`F2:side:c1`). Once the stem grew, the name found the seam and SMLib refused the chamfer (join_extrude_from_a_chamfered_top_face). edge_names_for names the edge each pick takes as a blend takes it (kernel::blend_edges), the nearest edge only where that finds none. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+10
-2
@@ -3226,7 +3226,8 @@ pub fn edge_refs(st: &ModelState, body: &Option<crate::BodyName>, pts: &[Vec3])
|
||||
}
|
||||
|
||||
/// Persistent names of the edges picked at `pts`, each on the body it lies on (see
|
||||
/// [`picked_bodies`]).
|
||||
/// [`picked_bodies`]): of the edge a blend takes at each pick (at a vertex where a seam meets a
|
||||
/// rim, the rim), else of the nearest edge.
|
||||
pub fn edge_names_for(st: &ModelState, body: &Option<crate::BodyName>, pts: &[Vec3]) -> Vec<String> {
|
||||
let Some(on) = picked_bodies(st, body, pts) else { return Vec::new() };
|
||||
let mut out = vec![String::new(); pts.len()];
|
||||
@@ -3240,7 +3241,14 @@ pub fn edge_names_for(st: &ModelState, body: &Option<crate::BodyName>, pts: &[Ve
|
||||
// The body's names are worked out once for all its picks.
|
||||
let idx: Vec<usize> = on.iter().enumerate().filter(|(_, t)| **t == ti).map(|(i, _)| i).collect();
|
||||
let at: Vec<Vec3> = idx.iter().filter_map(|i| pts.get(*i).copied()).collect();
|
||||
for (i, n) in idx.into_iter().zip(crate::naming::edge_names_at(b, &at)) {
|
||||
let names = match kernel::blend_edges(&b.body, &at) {
|
||||
Ok(edges) => {
|
||||
let all = crate::naming::edge_names(b);
|
||||
edges.iter().map(|e| all.get(*e).cloned().unwrap_or_default()).collect()
|
||||
}
|
||||
Err(_) => crate::naming::edge_names_at(b, &at),
|
||||
};
|
||||
for (i, n) in idx.into_iter().zip(names) {
|
||||
if let Some(slot) = out.get_mut(i) {
|
||||
*slot = n;
|
||||
}
|
||||
|
||||
@@ -617,6 +617,13 @@ pub fn chamfer_sides(body: &Body, edges: &[Vec3], d1: f64, side: ChamferSide, fl
|
||||
crate::blend_smlib::chamfer_sides(body, edges, d1, side, flip)
|
||||
}
|
||||
|
||||
/// The edge each pick takes, as a blend takes it (an index in the body's edge order, the order
|
||||
/// of its mesh's edges): the nearest, and at a vertex where a seam or a smooth join meets a sharp
|
||||
/// edge (a cylinder's seam at its rim), the sharp edge. Picks that find no edge are refused.
|
||||
pub fn blend_edges(body: &Body, picks: &[Vec3]) -> Result<Vec<usize>> {
|
||||
crate::blend_smlib::picked_edges(body, picks).map(|(edges, _)| edges)
|
||||
}
|
||||
|
||||
/// The picked edges' tangent chains, for a blend that is to run along them: `picks` (each the
|
||||
/// nearest edge of `body` to it), then a point on every other edge that continues one of them
|
||||
/// tangentially (within 0.5° at a shared vertex), until no more do. Each pick takes its edge as a
|
||||
|
||||
@@ -155,8 +155,8 @@ mod validity;
|
||||
pub mod watch;
|
||||
|
||||
pub use blend::{
|
||||
ChamferSide, chamfer, chamfer_sides, fillet, fillet_each, fillet_g2, fillet_g2_corners, fillet_least_setback, fillet_max, fillet_max_each,
|
||||
fillet_setback, tangent_chain,
|
||||
ChamferSide, blend_edges, chamfer, chamfer_sides, fillet, fillet_each, fillet_g2, fillet_g2_corners, fillet_least_setback, fillet_max,
|
||||
fillet_max_each, fillet_setback, tangent_chain,
|
||||
};
|
||||
pub use blend_corner::fillet_radii;
|
||||
pub use blend_variable::{RadiusSpline, Taper, fillet_chord, fillet_tapered, fillet_variable, fillet_variable_points, fillet_variable_spline, taper};
|
||||
|
||||
Reference in New Issue
Block a user