Complete FILLETEDGE workflow and history

This commit is contained in:
ramox81 committed 2026-09-08 12:36:49 +03:00
1 parent febedad916
commit 8bb6703c70
16 files changed
+901 -71

No files matched your search

+2 -2
View File
@@ -596,8 +596,8 @@ impl Scene {
.filter_map(|&handle| {
let from_history = self
.document
.solid_history_operation(handle)
.and_then(|operation| cadkernel::acis::rebuild_body(operation).ok());
.solid_history_operations(handle)
.and_then(|operations| cadkernel::acis::rebuild_history(&operations).ok());
let body = from_history.or_else(|| match self.document.get_entity(handle) {
Some(EntityType::Solid3D(solid)) => {
crate::scene::convert::solid3d_tess::kernel_body(solid)
+71 -2
View File
@@ -1,12 +1,12 @@
use acadrust::entities::{EmbeddedEntity, Solid3D};
use acadrust::objects::{
DynamicBlockData, ObjectType, SolidHistoryBox, SolidHistoryBrep, SolidHistoryCone,
SolidHistoryCylinder, SolidHistoryLoft, SolidHistoryLoftParameters, SolidHistoryNodeBase, SolidHistoryOperation,
SolidHistoryCylinder, SolidHistoryFillet, SolidHistoryLoft, SolidHistoryLoftParameters, SolidHistoryNodeBase, SolidHistoryOperation,
SolidHistoryPyramid, SolidHistoryRevolve, SolidHistorySphere, SolidHistorySweep,
SolidHistoryTorus,
};
use acadrust::EntityType;
use cadkernel::brep::Body;
use cadkernel::brep::{Body, Surface};
use crate::command::EntityTransform;
use crate::entities::traits::EntityTypeOps;
@@ -32,6 +32,7 @@ pub const GRIP_SWEEP_PATH_FIRST: usize = 30_000;
pub const GRIP_LOFT_SECTION_FIRST: usize = 40_000;
pub const GRIP_REVOLVE_PROFILE_FIRST: usize = 50_000;
pub const GRIP_REVOLVE_AXIS: usize = 10_013;
pub const GRIP_FILLET_RADIUS: usize = 10_014;
pub const GRIP_BOX_CORNER_FIRST: usize = 10_100;
pub const GRIP_BOX_FACE_X_MIN: usize = 10_110;
pub const GRIP_BOX_FACE_X_MAX: usize = 10_111;
@@ -3086,6 +3087,51 @@ fn grip(
}
}
pub fn fillet_radius_grip(body: &Body, radius: f64) -> Option<GripDef> {
if !radius.is_finite() || radius <= 0.0 {
return None;
}
for (face_key, face) in body.faces.iter() {
let Some(Surface::Cylinder(cylinder)) = body.surfaces.get(face.surface) else {
continue;
};
if (cylinder.radius.abs() - radius).abs() > radius.max(1.0) * 1.0e-7 {
continue;
}
let axis = glam::DVec3::from_array(cylinder.base.normal()?).try_normalize()?;
let origin = glam::DVec3::from_array(cylinder.base.origin);
let points = body
.face_coedges(face_key)
.into_iter()
.filter_map(|coedge| body.coedges.get(coedge))
.filter_map(|coedge| body.edges.get(coedge.edge))
.flat_map(|edge| [edge.start, edge.end])
.filter_map(|vertex| body.vertices.get(vertex))
.map(|vertex| glam::DVec3::from_array(vertex.point))
.collect::<Vec<_>>();
let minimum = points
.iter()
.map(|point| (*point - origin).dot(axis))
.reduce(f64::min)?;
let maximum = points
.iter()
.map(|point| (*point - origin).dot(axis))
.reduce(f64::max)?;
let center = origin + axis * ((minimum + maximum) * 0.5);
let radial = points
.iter()
.map(|point| *point - center - axis * (*point - center).dot(axis))
.find_map(|radial| radial.try_normalize())?;
return Some(grip(
GRIP_FILLET_RADIUS,
center + radial * radius,
GripShape::Square,
Some(radial),
));
}
None
}
pub fn primitive_grips(
document: &acadrust::CadDocument,
handle: acadrust::Handle,
@@ -3093,6 +3139,18 @@ pub fn primitive_grips(
let Some(operation) = document.solid_history_operation(handle) else {
return Vec::new();
};
if let SolidHistoryOperation::Fillet(value) = operation {
let Some(radius) = value.radii.first().copied() else {
return Vec::new();
};
let Some(EntityType::Solid3D(solid)) = document.get_entity(handle) else {
return Vec::new();
};
return crate::scene::convert::solid3d_tess::kernel_body(solid)
.and_then(|body| fillet_radius_grip(&body, radius))
.into_iter()
.collect();
}
let mut grips = Vec::new();
let mut add = |id, transform, point, shape, axis: Option<[f64; 3]>| {
if let Some(world) = world_point(transform, point) {
@@ -3713,3 +3771,14 @@ pub fn brep_op(body: &Body) -> SolidHistoryOperation {
..SolidHistoryBrep::default()
})
}
pub fn fillet_op(edges: Vec<i32>, radius: f64) -> SolidHistoryOperation {
SolidHistoryOperation::Fillet(SolidHistoryFillet {
base: base(glam::DMat4::IDENTITY.to_cols_array()),
operation_major: 1,
method: 0,
edges,
radii: vec![radius],
..SolidHistoryFillet::default()
})
}
+63 -2
View File
@@ -802,6 +802,29 @@ impl Scene {
true
}
pub fn append_solid_history(
&mut self,
handle: Handle,
operation: acadrust::objects::SolidHistoryOperation,
) -> bool {
let previous = self
.document
.solid_history_graph(handle)
.map(|graph| graph.nodes)
.unwrap_or_default();
self.record_solid_history_before(handle);
let Some(graph) = self.document.append_solid_history(handle, operation) else {
return false;
};
for node in graph.nodes {
if !previous.contains(&node) {
self.record_undo_object_before(node, None);
}
}
self.sync_solid_reference_point(handle);
true
}
pub(crate) fn sync_solid_reference_point(&mut self, handle: Handle) {
let reference = self
.document
@@ -855,8 +878,14 @@ impl Scene {
(EntityType::Surface(_), SolidHistoryOperation::Extrusion(value)) => {
cadkernel::acis::rebuild_extrusion_with_mode(value, true).ok()
}
(EntityType::Surface(_), SolidHistoryOperation::Loft(_))
| (EntityType::Solid3D(_), _) => cadkernel::acis::rebuild_body(operation).ok(),
(EntityType::Surface(_), SolidHistoryOperation::Loft(_)) => {
cadkernel::acis::rebuild_body(operation).ok()
}
(EntityType::Solid3D(_), _) => {
let mut operations = self.document.solid_history_operations(handle)?;
*operations.last_mut()? = operation.clone();
cadkernel::acis::rebuild_history(&operations).ok()
}
_ => None,
}
}
@@ -1122,6 +1151,38 @@ impl Scene {
let Some(mut operation) = self.document.solid_history_operation(handle).cloned() else {
return false;
};
if grip_id == crate::scene::model::solid_history::GRIP_FILLET_RADIUS {
let acadrust::objects::SolidHistoryOperation::Fillet(value) = &mut operation else {
return false;
};
let Some(radius) = value.radii.first().copied() else {
return false;
};
self.restore_solid_models(&[handle]);
let Some(definition) = self
.solid_models
.get(&handle)
.and_then(|body| {
crate::scene::model::solid_history::fillet_radius_grip(body, radius)
})
else {
return false;
};
let Some(axis) = definition.axis else {
return false;
};
let change = match apply {
GripApply::Absolute(world) => (world - definition.world).dot(axis),
GripApply::Translate(delta) => delta.dot(axis),
};
let radius = radius + change;
if !radius.is_finite() || radius <= 1.0e-6 {
return false;
}
value.radii.clear();
value.radii.push(radius);
return self.preview_solid_history(handle, operation);
}
if !crate::scene::model::solid_history::apply_primitive_grip(
&mut operation,
grip_id,