forked from 1b-agent/opencadstudio-upstream
Restore region bounds and exact profile measurements after reload
This commit is contained in:
1 parent
7d0c059b30
commit
b42ae9d4a8
3 files changed
+34
-13
No files matched your search
+4
-1
@@ -1244,11 +1244,14 @@ impl DocApiBackend for HostSession<'_> {
|
||||
|
||||
fn bounds(&mut self, id: ObjectId) -> ApiResult<Aabb> {
|
||||
let handle = obj_to_handle(id);
|
||||
// Lift-on-miss for solids (consistent with volume/centroid); borrow the cache
|
||||
// Lift-on-miss for modeler geometry (consistent with volume/centroid); borrow the cache
|
||||
// read-only via with_body (O(1), no B-rep deep clone).
|
||||
if matches!(
|
||||
self.document().get_entity(handle),
|
||||
Some(EntityType::Solid3D(_))
|
||||
) || matches!(
|
||||
self.document().get_entity(handle),
|
||||
Some(EntityType::Region(region)) if region.acis_data.has_data()
|
||||
) {
|
||||
let mut f = |body: &KernelBody| -> ApiResult<Aabb> {
|
||||
let bb = cadkernel::brep::body_bounds(body)
|
||||
|
||||
+21
-12
@@ -260,17 +260,26 @@ fn position_section(prefix: &str, p: &acadrust::types::Vector3) -> PropSection {
|
||||
}
|
||||
}
|
||||
|
||||
/// Approximate a region's enclosed area and boundary perimeter from its
|
||||
/// wireframe loops. Perimeter is the total edge length across every wire.
|
||||
/// Area accumulates the Newell area vector of each loop (opposite-wound
|
||||
/// holes subtract) and halves its magnitude — exact for a single planar
|
||||
/// loop, approximate for multi-loop or curved regions. Returns zeros when
|
||||
/// there is nothing to measure.
|
||||
/// The area and perimeter of a region's boundary wires.
|
||||
///
|
||||
/// Measured in space rather than in projection: a region need not lie in a
|
||||
/// coordinate plane, and flattening it to XY first would report its shadow.
|
||||
fn region_area_perimeter(wires: &[acadrust::entities::Wire]) -> (f64, f64) {
|
||||
/// Measure decoded planar curves in a unit frame, retaining legacy wire-only input.
|
||||
fn region_area_perimeter(region: &Region) -> (f64, f64) {
|
||||
let exact = (|| {
|
||||
let (plane, loops, true) = crate::scene::model::presspull_model::profile_geometry(
|
||||
&EntityType::Region(region.clone()),
|
||||
)? else { return None; };
|
||||
let unit = cadkernel::space::Plane::orthonormal(plane.origin, plane.x_axis, plane.normal()?)?;
|
||||
let transform = cadkernel::geom2d::Transform {
|
||||
origin: unit.project(plane.origin)?.into(),
|
||||
x_axis: unit.project_vector(plane.x_axis)?.into(),
|
||||
y_axis: unit.project_vector(plane.y_axis)?.into(),
|
||||
};
|
||||
let curves = loops.iter().flatten().map(|curve| curve.transformed(&transform))
|
||||
.collect::<Option<Vec<_>>>()?;
|
||||
let area = curves.iter().map(|curve| curve.enclosed_area()).sum::<f64>().abs();
|
||||
let perimeter = curves.iter().map(|curve| curve.length()).sum::<f64>();
|
||||
(area.is_finite() && perimeter.is_finite()).then_some((area, perimeter))
|
||||
})();
|
||||
if let Some(measurements) = exact { return measurements; }
|
||||
let wires = ®ion.wires;
|
||||
let mut area_vector = [0.0f64; 3];
|
||||
let mut perimeter = 0.0;
|
||||
for wire in wires {
|
||||
@@ -351,7 +360,7 @@ impl Grippable for Region {
|
||||
|
||||
impl PropertyEditable for Region {
|
||||
fn geometry_properties(&self, _text_style_names: &[String]) -> Vec<PropSection> {
|
||||
let (area, perimeter) = region_area_perimeter(&self.wires);
|
||||
let (area, perimeter) = region_area_perimeter(self);
|
||||
let mut sections =
|
||||
acis_sections(&self.acis_data, &self.wires, &self.silhouettes, self.history_handle);
|
||||
sections[0]
|
||||
|
||||
@@ -1719,6 +1719,15 @@ pub(crate) fn set_wire_aabb(w: &mut WireModel, entity_box: [f32; 4]) {
|
||||
}
|
||||
|
||||
fn entity_bounds(e: &acadrust::EntityType) -> ([f64; 3], [f64; 3]) {
|
||||
if let acadrust::EntityType::Region(region) = e {
|
||||
if region.wires.is_empty() {
|
||||
if let Some(bounds) = super::solid3d_tess::kernel_region_body(region)
|
||||
.and_then(|body| cadkernel::brep::body_bounds(&body))
|
||||
{
|
||||
return (bounds.min, bounds.max);
|
||||
}
|
||||
}
|
||||
}
|
||||
if let acadrust::EntityType::Line(line) = e {
|
||||
if let Some(association) = acadrust::entities::CenterMarkAssociation::read(
|
||||
&line.common.extended_data,
|
||||
|
||||
Reference in new issue
Block a user