Fix active intersection snapping

This commit is contained in:
gianlucafiore committed 2026-08-08 21:20:40 -03:00
1 parent 5bd5c884e0
commit 15727bbffe
2 files changed
+300 -7

No files matched your search

+157 -7
View File
@@ -982,11 +982,61 @@ impl OpenCADStudio {
// hot-grip set is moved by the same drag vector.
self.snapper.from_point = Some(grip.origin_world.as_vec3());
let (go, gr) = self.tabs[i].ucs_grid_basis();
let base = grip.origin_world;
let ucs_xf = self.tabs[i].ucs_xform();
let mut construction_cursor = if self.ortho_mode {
Some(ortho_constrain(raw, base, &ucs_xf))
} else if self.polar_mode {
let pt = polar_constrain_near(
raw,
base,
self.polar_increment_deg,
view_rot,
eye,
bounds,
self.snapper.osnap_radius_px,
&ucs_xf,
);
// POLAR must actually be engaged on one of its rays.
let delta = pt - base;
let step = (self.polar_increment_deg as f64).to_radians();
let angle = delta.y.atan2(delta.x);
let polar_engaged = step > 1e-9
&& (((angle / step).round() * step - angle).abs() < 1e-3)
&& (delta.x * delta.x + delta.y * delta.y).sqrt() > 1e-9;
if polar_engaged {
Some(pt)
} else {
None
}
} else {
None
};
if let Some(pt) = construction_cursor.as_mut() {
if self.tabs[i].active_ucs.is_none() {
pt.z = base.z;
}
}
// `raw` is already model space (viewport camera or paper→model),
// and the wires are model space, so the snap result is model.
let snap_hit =
self.snapper
.snap(raw, p, &snap_candidates, view_rot, eye, bounds, go, gr);
let snap_hit = self.snapper.snap(
raw,
p,
&snap_candidates,
view_rot,
eye,
bounds,
go,
gr,
construction_cursor,
);
self.tabs[i].snap_result = snap_hit;
@@ -1391,10 +1441,60 @@ impl OpenCADStudio {
)
} else {
let (go, gr) = self.tabs[i].ucs_grid_basis();
// The snapper is a screen-space (f32) engine; the f64
// base only matters for typed-input precision, so hand it
// the downcast point here.
// The point the active rubber-band starts from.
self.snapper.from_point = self.last_point.map(|p| p.as_vec3());
// Build the temporary construction direction before OSNAP.
// Intersection can then test the active rubber-band against
// existing geometry (#704).
let construction_cursor = if is_window_corner {
None
} else {
self.last_point.and_then(|base| {
let ucs_xf = self.tabs[i].ucs_xform();
let mut pt = if self.ortho_mode {
Some(ortho_constrain(snap_cursor, base, &ucs_xf))
} else if self.polar_mode {
let pt = polar_constrain_near(
snap_cursor,
base,
self.polar_increment_deg,
view_rot,
eye,
bounds,
self.snapper.osnap_radius_px,
&ucs_xf,
);
// POLAR being enabled is not enough: the cursor must actually
// be engaged on one of the polar tracking rays.
let delta = pt - base;
let step = (self.polar_increment_deg as f64).to_radians();
let angle = delta.y.atan2(delta.x);
let polar_engaged = step > 1e-9
&& (((angle / step).round() * step - angle).abs() < 1e-3)
&& (delta.x * delta.x + delta.y * delta.y).sqrt() > 1e-9;
if polar_engaged {
Some(pt)
} else {
None
}
} else {
None
}?;
if self.tabs[i].active_ucs.is_none() {
pt.z = base.z;
}
Some(pt)
})
};
self.snapper.snap(
snap_cursor,
p,
@@ -1404,6 +1504,7 @@ impl OpenCADStudio {
bounds,
go,
gr,
construction_cursor,
)
};
@@ -2047,7 +2148,7 @@ impl OpenCADStudio {
let (go, gr) = self.tabs[i].ucs_grid_basis();
let snap_hit = self
.snapper
.snap(raw, p, &snap_candidates, view_rot, eye, bounds, go, gr);
.snap(raw, p, &snap_candidates, view_rot, eye, bounds, go, gr, None);
let world = snap_hit.map(|s| s.world).unwrap_or(raw);
self.tabs[i].snap_result = snap_hit;
if let Some(s) = self.tabs[i].snap_result.as_mut() {
@@ -2692,6 +2793,54 @@ impl OpenCADStudio {
} else {
let (go, gr) = self.tabs[i].ucs_grid_basis();
self.snapper.from_point = self.last_point.map(|p| p.as_vec3());
let construction_cursor = if is_window_corner {
None
} else {
self.last_point.and_then(|base| {
let ucs_xf = self.tabs[i].ucs_xform();
let mut pt = if self.ortho_mode {
Some(ortho_constrain(snap_cursor, base, &ucs_xf))
} else if self.polar_mode {
let pt = polar_constrain_near(
snap_cursor,
base,
self.polar_increment_deg,
view_rot,
eye,
bounds,
self.snapper.osnap_radius_px,
&ucs_xf,
);
// POLAR being enabled is not enough: the cursor must actually
// be engaged on one of the polar tracking rays.
let delta = pt - base;
let step = (self.polar_increment_deg as f64).to_radians();
let angle = delta.y.atan2(delta.x);
let polar_engaged = step > 1e-9
&& (((angle / step).round() * step - angle).abs() < 1e-3)
&& (delta.x * delta.x + delta.y * delta.y).sqrt() > 1e-9;
if polar_engaged {
Some(pt)
} else {
None
}
} else {
None
}?;
if self.tabs[i].active_ucs.is_none() {
pt.z = base.z;
}
Some(pt)
})
};
self.snapper.snap(
snap_cursor,
p,
@@ -2701,6 +2850,7 @@ impl OpenCADStudio {
bounds,
go,
gr,
construction_cursor,
)
};
// Snap runs in model space; the result is already model.