forked from 1b-agent/opencadstudio-upstream
fix(solids): box and wedge histories framed at the bounding-box centre; no second transform after ACIS lift
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
a21aef2a11
commit
07facf465c
6 files changed
+74
-35
No files matched your search
Generated
+3
-3
@@ -4206,7 +4206,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "opencadcodec"
|
name = "opencadcodec"
|
||||||
version = "0.5.5"
|
version = "0.5.5"
|
||||||
source = "git+https://github.com/HakanSeven12/opencadcodec.git?rev=d96e3fa#d96e3fa2fe5acbeac966f1db4c01142618bf9c79"
|
source = "git+https://github.com/ramox81/cadcodec.git?rev=1802e8c#1802e8cc4d213da60156e7e540965ea398768d18"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ahash 0.8.12",
|
"ahash 0.8.12",
|
||||||
"anyhow",
|
"anyhow",
|
||||||
@@ -4238,7 +4238,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "opencadkernel"
|
name = "opencadkernel"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/HakanSeven12/opencadkernel.git?rev=9cdd36d#9cdd36dc527216ba7929d8cfcdc1b7712a2d4cb8"
|
source = "git+https://github.com/ramox81/cadkernel.git?rev=6dc98c6#6dc98c6749af2b6e0586eb4279eb5e389dd2aa16"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cavalier_contours",
|
"cavalier_contours",
|
||||||
"opencadcodec",
|
"opencadcodec",
|
||||||
@@ -4249,7 +4249,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "opencadkernel-constraints"
|
name = "opencadkernel-constraints"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/HakanSeven12/opencadkernel.git?rev=9cdd36d#9cdd36dc527216ba7929d8cfcdc1b7712a2d4cb8"
|
source = "git+https://github.com/ramox81/cadkernel.git?rev=6dc98c6#6dc98c6749af2b6e0586eb4279eb5e389dd2aa16"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"nalgebra",
|
"nalgebra",
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -90,6 +90,15 @@ objc2-app-kit = { version = "0.2", features = ["NSApplication", "NSResponder", "
|
|||||||
block2 = "0.5"
|
block2 = "0.5"
|
||||||
objc2-foundation = { version = "0.2", features = ["NSArray", "NSURL", "NSString", "NSObject", "NSNotification", "NSThread", "NSEnumerator"] }
|
objc2-foundation = { version = "0.2", features = ["NSArray", "NSURL", "NSString", "NSObject", "NSNotification", "NSThread", "NSEnumerator"] }
|
||||||
|
|
||||||
|
# Column-major history matrices and embedded circle centres (opencadcodec #77).
|
||||||
|
[patch."https://github.com/HakanSeven12/opencadcodec.git"]
|
||||||
|
opencadcodec = { git = "https://github.com/ramox81/cadcodec.git", rev = "1802e8c" }
|
||||||
|
|
||||||
|
# Box frame at the centre and transform-aware ACIS lift (opencadkernel #73).
|
||||||
|
[patch."https://github.com/HakanSeven12/opencadkernel.git"]
|
||||||
|
opencadkernel = { git = "https://github.com/ramox81/cadkernel.git", rev = "6dc98c6" }
|
||||||
|
opencadkernel-constraints = { git = "https://github.com/ramox81/cadkernel.git", rev = "6dc98c6" }
|
||||||
|
|
||||||
[patch.crates-io]
|
[patch.crates-io]
|
||||||
iced_core = { git = "https://github.com/iced-rs/iced.git", rev = "23604ff22ab0aad9e00b9327cb7b8546ed84db39" }
|
iced_core = { git = "https://github.com/iced-rs/iced.git", rev = "23604ff22ab0aad9e00b9327cb7b8546ed84db39" }
|
||||||
iced_widget = { git = "https://github.com/iced-rs/iced.git", rev = "23604ff22ab0aad9e00b9327cb7b8546ed84db39" }
|
iced_widget = { git = "https://github.com/iced-rs/iced.git", rev = "23604ff22ab0aad9e00b9327cb7b8546ed84db39" }
|
||||||
|
|||||||
@@ -1894,7 +1894,7 @@ impl PrimitiveCommand {
|
|||||||
Some((
|
Some((
|
||||||
placed,
|
placed,
|
||||||
solid_history::box_op(
|
solid_history::box_op(
|
||||||
self.history_transform_axes(origin, x_axis, y_axis),
|
self.history_transform_axes(box_centre(origin, x_axis, y_axis, length, width, height), x_axis, y_axis),
|
||||||
length,
|
length,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
@@ -2024,7 +2024,7 @@ impl PrimitiveCommand {
|
|||||||
Some((
|
Some((
|
||||||
placed,
|
placed,
|
||||||
solid_history::wedge_op(
|
solid_history::wedge_op(
|
||||||
self.history_transform_axes(origin, x_axis, y_axis),
|
self.history_transform_axes(box_centre(origin, x_axis, y_axis, length, width, height), x_axis, y_axis),
|
||||||
length,
|
length,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
@@ -3714,3 +3714,9 @@ fn wire(name: &str, points: Vec<[f32; 3]>) -> WireModel {
|
|||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Box and wedge histories are framed at the centre of their bounding box,
|
||||||
|
/// as the reference stores them (lengths stay positive).
|
||||||
|
fn box_centre(origin: DVec3, x_axis: DVec3, y_axis: DVec3, length: f64, width: f64, height: f64) -> DVec3 {
|
||||||
|
origin + x_axis * (length * 0.5) + y_axis * (width * 0.5) + DVec3::Z * (height * 0.5)
|
||||||
|
}
|
||||||
@@ -31,23 +31,14 @@ pub fn tessellate_sat(
|
|||||||
if bodies.is_empty() {
|
if bodies.is_empty() {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
// The kernel's lift already applies each body's transform record; its
|
||||||
|
// scale still sets the tessellation tolerance.
|
||||||
let mut placed_bodies = Vec::with_capacity(bodies.len());
|
let mut placed_bodies = Vec::with_capacity(bodies.len());
|
||||||
for body in bodies {
|
for body in bodies {
|
||||||
let source = body.provenance.source()?;
|
let source = body.provenance.source()?;
|
||||||
let transform = body_transform(document, source.index() as usize).ok()?;
|
let transform = body_transform(document, source.index() as usize).ok()?;
|
||||||
let placement_scale = transform.map_or(1.0, |(_, _, scale)| scale.abs());
|
let placement_scale = transform.map_or(1.0, |(_, _, scale)| scale.abs());
|
||||||
let placed = if let Some((matrix, translation, scale)) = transform {
|
placed_bodies.push((body, placement_scale));
|
||||||
let placement = brep::Placement {
|
|
||||||
x_axis: [scale * matrix[0], scale * matrix[1], scale * matrix[2]],
|
|
||||||
y_axis: [scale * matrix[3], scale * matrix[4], scale * matrix[5]],
|
|
||||||
z_axis: [scale * matrix[6], scale * matrix[7], scale * matrix[8]],
|
|
||||||
origin: translation,
|
|
||||||
};
|
|
||||||
brep::transform(&body, &placement)?
|
|
||||||
} else {
|
|
||||||
body
|
|
||||||
};
|
|
||||||
placed_bodies.push((placed, placement_scale));
|
|
||||||
}
|
}
|
||||||
let bodies = placed_bodies;
|
let bodies = placed_bodies;
|
||||||
let resolution = if facet_res.is_finite() && facet_res > 0.0 {
|
let resolution = if facet_res.is_finite() && facet_res > 0.0 {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use codec::entities::acis::{SabReader, SatBody, SatDocument};
|
use codec::entities::acis::{SabReader, SatBody, SatDocument};
|
||||||
use codec::entities::{Body, Region, Solid3D, Surface};
|
use codec::entities::{Body, Region, Solid3D, Surface};
|
||||||
use kernel::brep::{self, Body as KernelBody};
|
use kernel::brep::Body as KernelBody;
|
||||||
|
|
||||||
use crate::scene::model::mesh_model::{MeshLodSet, MeshModel};
|
use crate::scene::model::mesh_model::{MeshLodSet, MeshModel};
|
||||||
|
|
||||||
@@ -179,21 +179,8 @@ pub(crate) fn kernel_acis_body(acis: &codec::entities::AcisData) -> Option<Kerne
|
|||||||
if !loss.is_empty() || bodies.len() != 1 {
|
if !loss.is_empty() || bodies.len() != 1 {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
let body = bodies.pop()?;
|
// The kernel's lift already applies the body's transform record.
|
||||||
let source = body.provenance.source()?;
|
bodies.pop()
|
||||||
let Some((matrix, translation, scale)) = body_transform(&sat, source.index() as usize).ok()?
|
|
||||||
else {
|
|
||||||
return Some(body);
|
|
||||||
};
|
|
||||||
brep::transform(
|
|
||||||
&body,
|
|
||||||
&brep::Placement {
|
|
||||||
x_axis: [scale * matrix[0], scale * matrix[1], scale * matrix[2]],
|
|
||||||
y_axis: [scale * matrix[3], scale * matrix[4], scale * matrix[5]],
|
|
||||||
z_axis: [scale * matrix[6], scale * matrix[7], scale * matrix[8]],
|
|
||||||
origin: translation,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remap_acis_material_bindings(
|
fn remap_acis_material_bindings(
|
||||||
|
|||||||
@@ -278,7 +278,7 @@ pub fn reference_point(operation: &SolidHistoryOperation) -> Option<glam::DVec3>
|
|||||||
match operation {
|
match operation {
|
||||||
SolidHistoryOperation::Box(value) | SolidHistoryOperation::Wedge(value) => world_point(
|
SolidHistoryOperation::Box(value) | SolidHistoryOperation::Wedge(value) => world_point(
|
||||||
value.base.transform,
|
value.base.transform,
|
||||||
[value.length * 0.5, value.width * 0.5, 0.0],
|
[0.0, 0.0, -value.height * 0.5],
|
||||||
),
|
),
|
||||||
SolidHistoryOperation::Sphere(value) => {
|
SolidHistoryOperation::Sphere(value) => {
|
||||||
world_point(value.base.transform, [0.0, 0.0, 0.0])
|
world_point(value.base.transform, [0.0, 0.0, 0.0])
|
||||||
@@ -1615,9 +1615,10 @@ pub fn primitive_properties(
|
|||||||
) {
|
) {
|
||||||
return Vec::new();
|
return Vec::new();
|
||||||
}
|
}
|
||||||
let Some(operation) = primitive_property_operation(document, handle) else {
|
let Some(mut operation) = primitive_property_operation(document, handle) else {
|
||||||
return brep_properties(document, handle);
|
return brep_properties(document, handle);
|
||||||
};
|
};
|
||||||
|
corner_frame(&mut operation);
|
||||||
match &operation {
|
match &operation {
|
||||||
SolidHistoryOperation::Box(value) => {
|
SolidHistoryOperation::Box(value) => {
|
||||||
rectangular_properties(document, handle, value, "Box")
|
rectangular_properties(document, handle, value, "Box")
|
||||||
@@ -2414,6 +2415,17 @@ pub fn apply_primitive_property(
|
|||||||
operation: &mut SolidHistoryOperation,
|
operation: &mut SolidHistoryOperation,
|
||||||
field: &str,
|
field: &str,
|
||||||
value: &str,
|
value: &str,
|
||||||
|
) -> bool {
|
||||||
|
corner_frame(operation);
|
||||||
|
let applied = apply_primitive_property_at_corner(operation, field, value);
|
||||||
|
centre_frame(operation);
|
||||||
|
applied
|
||||||
|
}
|
||||||
|
|
||||||
|
fn apply_primitive_property_at_corner(
|
||||||
|
operation: &mut SolidHistoryOperation,
|
||||||
|
field: &str,
|
||||||
|
value: &str,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
if let SolidHistoryOperation::Brep(brep_value) = operation {
|
if let SolidHistoryOperation::Brep(brep_value) = operation {
|
||||||
if let Some(applied) = apply_brep_position_property(brep_value, field, value) {
|
if let Some(applied) = apply_brep_position_property(brep_value, field, value) {
|
||||||
@@ -3460,6 +3472,9 @@ pub fn primitive_grips(
|
|||||||
let Some(operation) = document.solid_history_operation(handle) else {
|
let Some(operation) = document.solid_history_operation(handle) else {
|
||||||
return Vec::new();
|
return Vec::new();
|
||||||
};
|
};
|
||||||
|
let mut operation = operation.clone();
|
||||||
|
corner_frame(&mut operation);
|
||||||
|
let operation = &operation;
|
||||||
if let SolidHistoryOperation::Fillet(value) = operation {
|
if let SolidHistoryOperation::Fillet(value) = operation {
|
||||||
let Some(radius) = value.radii.first().copied() else {
|
let Some(radius) = value.radii.first().copied() else {
|
||||||
return Vec::new();
|
return Vec::new();
|
||||||
@@ -3743,6 +3758,17 @@ pub fn apply_primitive_grip(
|
|||||||
operation: &mut SolidHistoryOperation,
|
operation: &mut SolidHistoryOperation,
|
||||||
grip_id: usize,
|
grip_id: usize,
|
||||||
apply: GripApply,
|
apply: GripApply,
|
||||||
|
) -> bool {
|
||||||
|
corner_frame(operation);
|
||||||
|
let applied = apply_primitive_grip_at_corner(operation, grip_id, apply);
|
||||||
|
centre_frame(operation);
|
||||||
|
applied
|
||||||
|
}
|
||||||
|
|
||||||
|
fn apply_primitive_grip_at_corner(
|
||||||
|
operation: &mut SolidHistoryOperation,
|
||||||
|
grip_id: usize,
|
||||||
|
apply: GripApply,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
if let SolidHistoryOperation::Revolve(value) = operation {
|
if let SolidHistoryOperation::Revolve(value) = operation {
|
||||||
if let Some(index) = grip_id.checked_sub(GRIP_REVOLVE_PROFILE_FIRST) {
|
if let Some(index) = grip_id.checked_sub(GRIP_REVOLVE_PROFILE_FIRST) {
|
||||||
@@ -4138,3 +4164,23 @@ pub fn chamfer_op(
|
|||||||
..SolidHistoryChamfer::default()
|
..SolidHistoryChamfer::default()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Box and wedge histories are framed at the centre of their bounding box,
|
||||||
|
/// as the reference stores them; the editing code here works in the frame at
|
||||||
|
/// the base corner. These move a box or wedge between the two frames.
|
||||||
|
fn corner_frame(operation: &mut SolidHistoryOperation) {
|
||||||
|
shift_rectangular_frame(operation, -0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn centre_frame(operation: &mut SolidHistoryOperation) {
|
||||||
|
shift_rectangular_frame(operation, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn shift_rectangular_frame(operation: &mut SolidHistoryOperation, factor: f64) {
|
||||||
|
if let SolidHistoryOperation::Box(value) | SolidHistoryOperation::Wedge(value) = operation {
|
||||||
|
if let Some(current) = matrix(value.base.transform) {
|
||||||
|
let half = glam::DVec3::new(value.length, value.width, value.height) * factor;
|
||||||
|
value.base.transform = (current * glam::DMat4::from_translation(half)).to_cols_array();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in new issue
Block a user