forked from 1b-agent/opencadstudio-upstream
Fix extruded solid grip preview and taper range
This commit is contained in:
1 parent
3ad0423393
commit
ea6eb58c53
8 files changed
+87
-10
No files matched your search
@@ -2314,7 +2314,7 @@ fn apply_extrusion_draft_grip(value: &mut SolidHistorySweep, apply: GripApply) -
|
||||
let GripApply::Absolute(world) = apply else {
|
||||
return false;
|
||||
};
|
||||
let Some((_, base_top, radial, profile_radius, height)) = extrusion_draft_grip(value) else {
|
||||
let Some((_, base_top, radial, _, height)) = extrusion_draft_grip(value) else {
|
||||
return false;
|
||||
};
|
||||
let top_offset = (world - base_top).dot(radial);
|
||||
@@ -2322,10 +2322,27 @@ fn apply_extrusion_draft_grip(value: &mut SolidHistorySweep, apply: GripApply) -
|
||||
return false;
|
||||
}
|
||||
let limit = 89.0_f64.to_radians();
|
||||
let inward_limit = ((profile_radius - 1e-6).max(1e-6) / height)
|
||||
.atan()
|
||||
.min(limit);
|
||||
let angle = (-top_offset).atan2(height).clamp(-limit, inward_limit);
|
||||
let desired = (-top_offset).atan2(height).clamp(-limit, limit);
|
||||
let angle = if desired > 0.0 && !extrusion_draft_rebuilds(value, desired) {
|
||||
// The maximum inset is profile-dependent. A corner radius is too
|
||||
// restrictive for many outlines, while allowing the pointer through
|
||||
// a collapsed outline makes the top grow again. Search the actual
|
||||
// rebuild boundary so every supported profile reaches its smallest
|
||||
// valid top without crossing into an inverted result.
|
||||
let mut valid = 0.0;
|
||||
let mut invalid = limit;
|
||||
for _ in 0..16 {
|
||||
let candidate = (valid + invalid) * 0.5;
|
||||
if extrusion_draft_rebuilds(value, candidate) {
|
||||
valid = candidate;
|
||||
} else {
|
||||
invalid = candidate;
|
||||
}
|
||||
}
|
||||
valid
|
||||
} else {
|
||||
desired
|
||||
};
|
||||
if !angle.is_finite() || (angle - value.draft_angle).abs() <= 1e-12 {
|
||||
return false;
|
||||
}
|
||||
@@ -2333,6 +2350,12 @@ fn apply_extrusion_draft_grip(value: &mut SolidHistorySweep, apply: GripApply) -
|
||||
true
|
||||
}
|
||||
|
||||
fn extrusion_draft_rebuilds(value: &SolidHistorySweep, angle: f64) -> bool {
|
||||
let mut candidate = value.clone();
|
||||
candidate.draft_angle = angle;
|
||||
cadkernel::acis::rebuild_body(&SolidHistoryOperation::Extrusion(candidate)).is_ok()
|
||||
}
|
||||
|
||||
fn grip(
|
||||
id: usize,
|
||||
world: glam::DVec3,
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
use cadkernel::brep::{self, Body, Curve3, EdgeKey, FaceKey, Surface};
|
||||
|
||||
use crate::scene::model::mesh_model::{MeshLodSet, MeshModel};
|
||||
use crate::scene::model::wire_model::WireModel;
|
||||
|
||||
/// What counts as the same point when the kernel checks a body over.
|
||||
const TOL: f64 = 1e-9;
|
||||
@@ -243,6 +244,27 @@ pub fn edge_wires(body: &Body) -> Vec<acadrust::entities::Wire> {
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// White wireframe used while a solid-history grip is hot.
|
||||
///
|
||||
/// This deliberately does not touch the resident solid mesh or its entity
|
||||
/// wires: the selected source stays visible in blue while the candidate body
|
||||
/// is presented as a separate, non-pickable outline until placement.
|
||||
pub fn grip_preview_wires(body: &Body, handle: acadrust::Handle) -> Vec<WireModel> {
|
||||
tessellation(body)
|
||||
.edges
|
||||
.into_iter()
|
||||
.filter(|edge| edge.positions.len() >= 2)
|
||||
.map(|edge| {
|
||||
WireModel::solid_f64(
|
||||
format!("{}-GRIP-PREVIEW", handle.value()),
|
||||
edge.positions,
|
||||
WireModel::WHITE,
|
||||
false,
|
||||
)
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// B-rep edge nearest a world-space surface pick.
|
||||
pub fn nearest_edge(body: &Body, pick: [f64; 3]) -> Option<EdgeKey> {
|
||||
let pick = cadkernel::space::Vec3::from(pick);
|
||||
|
||||
Reference in new issue
Block a user