forked from 1b-agent/opencadstudio-upstream
Merge pull request #1632 from ramox81/codex/sweep-miter-history
Sweep history records in the reference layout. Pins resolved to upstream: codec bff95f5 (#93, #94, #95, #96, #97 and review fixes), kernel 6146d31 (#75 and review fixes), graph 9635ba7.
This commit is contained in:
commit
0149a276ef
9 files changed
+65
-23
No files matched your search
Generated
+4
-4
@@ -4205,7 +4205,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "opencadcodec"
|
name = "opencadcodec"
|
||||||
version = "0.6.0"
|
version = "0.6.0"
|
||||||
source = "git+https://github.com/HakanSeven12/opencadcodec.git?rev=76d2a1c#76d2a1c66702d9aaf3ef8d4ff7dc06f4a025da82"
|
source = "git+https://github.com/HakanSeven12/opencadcodec.git?rev=bff95f5#bff95f5115dd9cc0c4983ba890c32f890948dfed"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"bitflags 2.13.1",
|
"bitflags 2.13.1",
|
||||||
@@ -4228,7 +4228,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "opencadgraph"
|
name = "opencadgraph"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/HakanSeven12/opencadgraph.git?rev=f8bbf40#f8bbf40282bce73e7a24ef4f242adf7617d6608e"
|
source = "git+https://github.com/HakanSeven12/opencadgraph.git?rev=9635ba7#9635ba7cdbf3b607548b1b2c30e2c10e2e2684d1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"opencadkernel",
|
"opencadkernel",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
@@ -4237,7 +4237,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=e13f37f#e13f37f88f4a24084aefceccca74a65500fec0ac"
|
source = "git+https://github.com/HakanSeven12/opencadkernel.git?rev=6146d31#6146d31e7ea6f240538af760b91c8640054d7466"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cavalier_contours",
|
"cavalier_contours",
|
||||||
"opencadcodec",
|
"opencadcodec",
|
||||||
@@ -4248,7 +4248,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=e13f37f#e13f37f88f4a24084aefceccca74a65500fec0ac"
|
source = "git+https://github.com/HakanSeven12/opencadkernel.git?rev=6146d31#6146d31e7ea6f240538af760b91c8640054d7466"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"nalgebra",
|
"nalgebra",
|
||||||
]
|
]
|
||||||
|
|||||||
+4
-4
@@ -34,10 +34,10 @@ rfd = "0.17"
|
|||||||
clap = { version = "4", features = ["derive", "string"] }
|
clap = { version = "4", features = ["derive", "string"] }
|
||||||
env_logger = "0.11"
|
env_logger = "0.11"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
codec = { package = "opencadcodec", git = "https://github.com/HakanSeven12/opencadcodec.git", rev = "76d2a1c", features = ["serde"] }
|
codec = { package = "opencadcodec", git = "https://github.com/HakanSeven12/opencadcodec.git", rev = "bff95f5", features = ["serde"] }
|
||||||
kernel = { package = "opencadkernel", git = "https://github.com/HakanSeven12/opencadkernel.git", rev = "e13f37f", features = ["acis", "offset"] }
|
kernel = { package = "opencadkernel", git = "https://github.com/HakanSeven12/opencadkernel.git", rev = "6146d31", features = ["acis", "offset"] }
|
||||||
kernel-constraints = { package = "opencadkernel-constraints", git = "https://github.com/HakanSeven12/opencadkernel.git", rev = "e13f37f" }
|
kernel-constraints = { package = "opencadkernel-constraints", git = "https://github.com/HakanSeven12/opencadkernel.git", rev = "6146d31" }
|
||||||
graph = { package = "opencadgraph", git = "https://github.com/HakanSeven12/opencadgraph.git", rev = "f8bbf40" }
|
graph = { package = "opencadgraph", git = "https://github.com/HakanSeven12/opencadgraph.git", rev = "9635ba7" }
|
||||||
dwg-thumbnailer = { path = "crates/dwg-thumbnailer" }
|
dwg-thumbnailer = { path = "crates/dwg-thumbnailer" }
|
||||||
flate2 = "1"
|
flate2 = "1"
|
||||||
image = { version = "0.25", default-features = false, features = ["png", "jpeg", "bmp", "tiff"] }
|
image = { version = "0.25", default-features = false, features = ["png", "jpeg", "bmp", "tiff"] }
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ serde_json = { version = "1", optional = true }
|
|||||||
# Pulled in only by the `host` feature, which adds the `opencadcodec`-typed
|
# Pulled in only by the `host` feature, which adds the `opencadcodec`-typed
|
||||||
# `HostApi` runtime surface. The default crate stays dependency-free so engine
|
# `HostApi` runtime surface. The default crate stays dependency-free so engine
|
||||||
# crates and external tooling can depend on the manifest/ribbon contract cheaply.
|
# crates and external tooling can depend on the manifest/ribbon contract cheaply.
|
||||||
codec = { package = "opencadcodec", git = "https://github.com/HakanSeven12/opencadcodec.git", rev = "76d2a1c", optional = true, features = ["serde"] }
|
codec = { package = "opencadcodec", git = "https://github.com/HakanSeven12/opencadcodec.git", rev = "bff95f5", optional = true, features = ["serde"] }
|
||||||
|
|
||||||
# Runtime IPC and serialization (host feature only).
|
# Runtime IPC and serialization (host feature only).
|
||||||
interprocess = { version = "2", optional = true }
|
interprocess = { version = "2", optional = true }
|
||||||
@@ -39,7 +39,7 @@ serde_json = "1"
|
|||||||
serde = { version = "1", features = ["derive"] }
|
serde = { version = "1", features = ["derive"] }
|
||||||
cargo-lock = "11"
|
cargo-lock = "11"
|
||||||
# opencadcodec is scanned at build time to generate the embedded type registry.
|
# opencadcodec is scanned at build time to generate the embedded type registry.
|
||||||
codec = { package = "opencadcodec", git = "https://github.com/HakanSeven12/opencadcodec.git", rev = "76d2a1c", features = ["serde"] }
|
codec = { package = "opencadcodec", git = "https://github.com/HakanSeven12/opencadcodec.git", rev = "bff95f5", features = ["serde"] }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
serde_json = "1"
|
serde_json = "1"
|
||||||
@@ -8,7 +8,7 @@ publish = false
|
|||||||
crate-type = ["cdylib"]
|
crate-type = ["cdylib"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
codec = { package = "opencadcodec", git = "https://github.com/HakanSeven12/opencadcodec.git", rev = "76d2a1c", features = ["serde"] }
|
codec = { package = "opencadcodec", git = "https://github.com/HakanSeven12/opencadcodec.git", rev = "bff95f5", features = ["serde"] }
|
||||||
bincode = "1.3"
|
bincode = "1.3"
|
||||||
serde = { version = "1", features = ["derive"] }
|
serde = { version = "1", features = ["derive"] }
|
||||||
console_error_panic_hook = "0.1"
|
console_error_panic_hook = "0.1"
|
||||||
|
|||||||
Generated
+1
-1
@@ -1264,7 +1264,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "opencadcodec"
|
name = "opencadcodec"
|
||||||
version = "0.6.0"
|
version = "0.6.0"
|
||||||
source = "git+https://github.com/HakanSeven12/opencadcodec.git?rev=76d2a1c#76d2a1c66702d9aaf3ef8d4ff7dc06f4a025da82"
|
source = "git+https://github.com/HakanSeven12/opencadcodec.git?rev=bff95f5#bff95f5115dd9cc0c4983ba890c32f890948dfed"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"bitflags",
|
"bitflags",
|
||||||
|
|||||||
@@ -486,6 +486,8 @@ impl OpenCADStudio {
|
|||||||
.iter()
|
.iter()
|
||||||
.map(|(_, entity)| entity.clone())
|
.map(|(_, entity)| entity.clone())
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
// Group 294: a base point the user picked.
|
||||||
|
let picked_base = options.base_point.is_some();
|
||||||
let options = sweep_model::sweep_selection_options(&selection, options);
|
let options = sweep_model::sweep_selection_options(&selection, options);
|
||||||
let pending = if profiles.is_empty() {
|
let pending = if profiles.is_empty() {
|
||||||
None
|
None
|
||||||
@@ -496,7 +498,8 @@ impl OpenCADStudio {
|
|||||||
let mut consumed = Vec::new();
|
let mut consumed = Vec::new();
|
||||||
for (handle, profile) in profiles {
|
for (handle, profile) in profiles {
|
||||||
let result = path.as_ref().zip(options).and_then(|(path, options)| {
|
let result = path.as_ref().zip(options).and_then(|(path, options)| {
|
||||||
let record = sweep_model::sweep_record(&profile, path, options)?;
|
let mut record = sweep_model::sweep_record(&profile, path, options)?;
|
||||||
|
record.flags_294_296[0] |= picked_base;
|
||||||
let (_, _, closed) = kernel::acis::sweep_profile_geometry(
|
let (_, _, closed) = kernel::acis::sweep_profile_geometry(
|
||||||
record.sweep_entity.as_ref()?,
|
record.sweep_entity.as_ref()?,
|
||||||
record.sweep_entity_transform,
|
record.sweep_entity_transform,
|
||||||
|
|||||||
@@ -315,7 +315,7 @@ fn history_operation_text(operation: &SolidHistoryOperation) -> String {
|
|||||||
value.base_face
|
value.base_face
|
||||||
),
|
),
|
||||||
SolidHistoryOperation::Sweep(value) | SolidHistoryOperation::Extrusion(value) => format!(
|
SolidHistoryOperation::Sweep(value) | SolidHistoryOperation::Extrusion(value) => format!(
|
||||||
"{}; sweep {}; path {}; direction {:.6},{:.6},{:.6}; draft {:.6}; scale {:.6}; twist {:.6}; align {:.6}; bank {}; intersections {}",
|
"{}; sweep {}; path {}; direction {:.6},{:.6},{:.6}; draft {:.6}; scale {:.6}; twist {:.6}; align {:.6}; align start {}; bank {}",
|
||||||
history_base_text(&value.base),
|
history_base_text(&value.base),
|
||||||
embedded_name(value.sweep_entity.as_ref()),
|
embedded_name(value.sweep_entity.as_ref()),
|
||||||
embedded_name(value.path_entity.as_ref()),
|
embedded_name(value.path_entity.as_ref()),
|
||||||
@@ -326,8 +326,8 @@ fn history_operation_text(operation: &SolidHistoryOperation) -> String {
|
|||||||
value.scale_factor,
|
value.scale_factor,
|
||||||
value.twist_angle,
|
value.twist_angle,
|
||||||
value.align_angle,
|
value.align_angle,
|
||||||
value.bank,
|
value.align_start,
|
||||||
value.check_intersections
|
value.bank
|
||||||
),
|
),
|
||||||
SolidHistoryOperation::Loft(value) => format!(
|
SolidHistoryOperation::Loft(value) => format!(
|
||||||
"{}; cross sections {}; guides {}",
|
"{}; cross sections {}; guides {}",
|
||||||
|
|||||||
@@ -651,7 +651,7 @@ pub fn extrusion_surface_data(
|
|||||||
path_entity_transform: value.path_entity_transform,
|
path_entity_transform: value.path_entity_transform,
|
||||||
is_solid: false,
|
is_solid: false,
|
||||||
sweep_alignment_flags: value.align_option as i16,
|
sweep_alignment_flags: value.align_option as i16,
|
||||||
align_start: value.has_align_start,
|
align_start: value.align_start,
|
||||||
bank: value.bank,
|
bank: value.bank,
|
||||||
base_point_set: true,
|
base_point_set: true,
|
||||||
reference_vector: value.reference_point,
|
reference_vector: value.reference_point,
|
||||||
|
|||||||
@@ -17,6 +17,24 @@ fn embedded_sweep_profile(entity: &EntityType) -> Option<(codec::entities::Embed
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The sweep path as the reference records it: a 3D polyline as a wire
|
||||||
|
/// body, anything else as its embedded entity.
|
||||||
|
fn embedded_sweep_path(path: &EntityType) -> Option<codec::entities::EmbeddedEntity> {
|
||||||
|
let EntityType::Polyline3D(value) = path else {
|
||||||
|
return embedded_path(path);
|
||||||
|
};
|
||||||
|
let points = value.vertices.iter()
|
||||||
|
.map(|vertex| [vertex.position.x, vertex.position.y, vertex.position.z])
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
let mut document = codec::entities::acis::SatDocument::new();
|
||||||
|
kernel::acis::append_polyline_wire(&points, value.is_closed(), &mut document).ok()?;
|
||||||
|
Some(codec::entities::EmbeddedEntity::Body {
|
||||||
|
// The 3D polyline object type.
|
||||||
|
type_code: 16,
|
||||||
|
acis_data: codec::entities::AcisData::from_sat(&document.to_sat_string()),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
pub fn is_sweep_profile(entity: &EntityType) -> bool {
|
pub fn is_sweep_profile(entity: &EntityType) -> bool {
|
||||||
embedded_sweep_profile(entity).is_some_and(|(profile, transform)| {
|
embedded_sweep_profile(entity).is_some_and(|(profile, transform)| {
|
||||||
kernel::acis::sweep_profile_geometry(&profile, transform).is_ok()
|
kernel::acis::sweep_profile_geometry(&profile, transform).is_ok()
|
||||||
@@ -64,10 +82,11 @@ pub fn sweep_record(profile: &EntityType, path: &EntityType, options: SweepOptio
|
|||||||
base,
|
base,
|
||||||
operation_major: 1,
|
operation_major: 1,
|
||||||
sweep_entity: Some(sweep_entity),
|
sweep_entity: Some(sweep_entity),
|
||||||
path_entity: Some(embedded_path(path)?),
|
path_entity: Some(embedded_sweep_path(path)?),
|
||||||
scale_factor: options.scale,
|
scale_factor: options.scale,
|
||||||
twist_angle: options.twist_angle,
|
twist_angle: options.twist_angle,
|
||||||
align_option: u8::from(options.align),
|
// 1 aligns the profile to the path; 2 only moves it to the path start.
|
||||||
|
align_option: if options.align { 1 } else { 2 },
|
||||||
has_align_start: true,
|
has_align_start: true,
|
||||||
bank: options.bank,
|
bank: options.bank,
|
||||||
sweep_entity_transform,
|
sweep_entity_transform,
|
||||||
@@ -100,12 +119,32 @@ fn placed_sweep_record(profile: &EntityType, mut record: SolidHistorySweep) -> O
|
|||||||
[0.0, 0.0, 0.0, 1.0],
|
[0.0, 0.0, 0.0, 1.0],
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
// The record's matrices are the source profile frame (at the base point,
|
||||||
|
// in the profile plane) and the frame it is placed in at the path start;
|
||||||
|
// the reference re-places the profile from them when it re-evaluates.
|
||||||
|
let (plane, _, _) = kernel::acis::sweep_profile_geometry(
|
||||||
|
record.sweep_entity.as_ref()?,
|
||||||
|
record.sweep_entity_transform,
|
||||||
|
).ok()?;
|
||||||
|
let x_axis = glam::DVec3::from_array(plane.x_axis).try_normalize()?;
|
||||||
|
let normal = glam::DVec3::from_array(plane.normal()?);
|
||||||
|
let base = glam::DVec3::new(record.reference_point.x, record.reference_point.y, record.reference_point.z);
|
||||||
|
let source_frame = glam::DMat4::from_cols(
|
||||||
|
x_axis.extend(0.0),
|
||||||
|
normal.cross(x_axis).extend(0.0),
|
||||||
|
normal.extend(0.0),
|
||||||
|
base.extend(1.0),
|
||||||
|
);
|
||||||
let mut moved = profile.clone();
|
let mut moved = profile.clone();
|
||||||
crate::scene::view::dispatch::apply_transform(&mut moved, &crate::command::EntityTransform::Affine(transform));
|
crate::scene::view::dispatch::apply_transform(&mut moved, &crate::command::EntityTransform::Affine(transform));
|
||||||
let (sweep_entity, sweep_entity_transform) = embedded_sweep_profile(&moved)?;
|
let (sweep_entity, _) = embedded_sweep_profile(&moved)?;
|
||||||
record.sweep_entity = Some(sweep_entity);
|
record.sweep_entity = Some(sweep_entity);
|
||||||
record.sweep_entity_transform = sweep_entity_transform;
|
record.sweep_entity_transform = source_frame.to_cols_array();
|
||||||
record.flags_294_296 = [false, true, true];
|
record.path_entity_transform = (map * source_frame).to_cols_array();
|
||||||
|
// Group 294 marks a profile only moved to the path, not turned onto it.
|
||||||
|
record.flags_294_296 = [record.align_option != 1, true, true];
|
||||||
|
// The reference records its default mitred joint.
|
||||||
|
record.miter_option = 2;
|
||||||
record.reference_point = Vector3::new(0.0, 0.0, 0.0);
|
record.reference_point = Vector3::new(0.0, 0.0, 0.0);
|
||||||
Some(record)
|
Some(record)
|
||||||
}
|
}
|
||||||
@@ -135,7 +174,7 @@ pub fn swept_surface_entity(record: &SolidHistorySweep) -> EntityType {
|
|||||||
sweep_entity_transform: record.sweep_entity_transform,
|
sweep_entity_transform: record.sweep_entity_transform,
|
||||||
path_entity_transform: record.path_entity_transform,
|
path_entity_transform: record.path_entity_transform,
|
||||||
sweep_alignment_flags: record.align_option as i16,
|
sweep_alignment_flags: record.align_option as i16,
|
||||||
align_start: record.has_align_start,
|
align_start: record.align_start,
|
||||||
bank: record.bank,
|
bank: record.bank,
|
||||||
base_point_set: true,
|
base_point_set: true,
|
||||||
reference_vector: record.reference_point,
|
reference_vector: record.reference_point,
|
||||||
|
|||||||
Reference in new issue
Block a user