forked from 1b-agent/opencadstudio-upstream
Merge pull request #961 from ramox81/codex/polysolid-parity
Align POLYSOLID sweep properties
This commit is contained in:
5 files changed
+130
-63
No files matched your search
Generated
+1
-1
@@ -878,7 +878,7 @@ checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04"
|
||||
[[package]]
|
||||
name = "cadkernel"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/HakanSeven12/cadkernel.git?rev=1e19ad4e4d35cc04384bf72bc9c6d0445876c2d9#1e19ad4e4d35cc04384bf72bc9c6d0445876c2d9"
|
||||
source = "git+https://github.com/HakanSeven12/cadkernel.git?rev=a809cb32cc6d90fd0e9c4199c3b4977cd56b7fa8#a809cb32cc6d90fd0e9c4199c3b4977cd56b7fa8"
|
||||
dependencies = [
|
||||
"acadrust",
|
||||
"cavalier_contours",
|
||||
|
||||
+1
-1
@@ -28,7 +28,7 @@ rfd = "0.17"
|
||||
clap = { version = "4", features = ["derive"] }
|
||||
env_logger = "0.11"
|
||||
acadrust = { git = "https://github.com/HakanSeven12/cadcodec.git", rev = "a0f7d444f1607bc4b2c881060cbe7ea1014253cb", features = ["serde"] }
|
||||
cadkernel = { git = "https://github.com/HakanSeven12/cadkernel.git", rev = "1e19ad4e4d35cc04384bf72bc9c6d0445876c2d9", features = ["acis", "offset"] }
|
||||
cadkernel = { git = "https://github.com/HakanSeven12/cadkernel.git", rev = "a809cb32cc6d90fd0e9c4199c3b4977cd56b7fa8", features = ["acis", "offset"] }
|
||||
dwg-thumbnailer = { path = "crates/dwg-thumbnailer" }
|
||||
flate2 = "1"
|
||||
image = { version = "0.25", default-features = false, features = ["png", "jpeg", "bmp", "tiff"] }
|
||||
|
||||
@@ -23,6 +23,7 @@ impl super::OpenCADStudio {
|
||||
let EntityType::Solid3D(inner) = &mut entity else {
|
||||
return Handle::NULL;
|
||||
};
|
||||
inner.common.plotstyle_flags = 2;
|
||||
inner.wires = solid_model::edge_wires(&solid);
|
||||
let Some(document) = crate::scene::convert::acis_export::solid_to_sat(&solid)
|
||||
else {
|
||||
|
||||
@@ -3066,9 +3066,7 @@ fn retain_specialized_primitive_sections(
|
||||
| "transparency"
|
||||
| "hyperlink"
|
||||
| "material"
|
||||
| "solid_history_type"
|
||||
) || crate::scene::model::solid_history::is_primitive_property(property.field)
|
||||
|| crate::scene::model::solid_history::is_history_choice(property.field)
|
||||
) || crate::scene::model::solid_history::is_specialized_property(property.field)
|
||||
});
|
||||
});
|
||||
sections.retain(|section| !section.props.is_empty());
|
||||
|
||||
@@ -52,6 +52,11 @@ pub const PROP_POSITION_X: &str = "solid_history_position_x";
|
||||
pub const PROP_POSITION_Y: &str = "solid_history_position_y";
|
||||
pub const PROP_POSITION_Z: &str = "solid_history_position_z";
|
||||
pub const PROP_ROTATION: &str = "solid_history_rotation";
|
||||
pub const PROP_PROFILE_ROTATION: &str = "solid_history_profile_rotation";
|
||||
pub const PROP_BANK: &str = "solid_history_bank";
|
||||
pub const PROP_TWIST_ALONG_PATH: &str = "solid_history_twist_along_path";
|
||||
pub const PROP_SCALE_ALONG_PATH: &str = "solid_history_scale_along_path";
|
||||
pub const PROP_SWEEP_LENGTH: &str = "solid_history_sweep_length";
|
||||
pub const PROP_PYRAMID_TYPE: &str = "solid_history_pyramid_type";
|
||||
pub const PROP_HISTORY: &str = "solid_history_record";
|
||||
pub const PROP_SHOW_HISTORY: &str = "solid_history_show";
|
||||
@@ -139,20 +144,14 @@ fn sweep_properties(
|
||||
handle: acadrust::Handle,
|
||||
value: &SolidHistorySweep,
|
||||
) -> Vec<PropSection> {
|
||||
let Some(position) = world_point(
|
||||
value.base.transform,
|
||||
[
|
||||
value.reference_point.x,
|
||||
value.reference_point.y,
|
||||
value.reference_point.z,
|
||||
],
|
||||
) else {
|
||||
return Vec::new();
|
||||
};
|
||||
let (record_history, object_show_history, show_history_mode) =
|
||||
history_flags(document, handle).unwrap_or((false, false, 1));
|
||||
let (show_history, _) = displayed_history_state(object_show_history, show_history_mode);
|
||||
let (show_history, show_history_editable) =
|
||||
displayed_history_state(object_show_history, show_history_mode);
|
||||
let show_value = if show_history { "Yes" } else { "No" };
|
||||
let length = sweep_path_length(value)
|
||||
.map(crate::entities::common::format_length)
|
||||
.unwrap_or_default();
|
||||
vec![
|
||||
PropSection {
|
||||
title: t!("Geometry").into_owned(),
|
||||
@@ -162,21 +161,37 @@ fn sweep_properties(
|
||||
field: "solid_history_type",
|
||||
value: PropValue::ReadOnly(t!("Sweep").into_owned()),
|
||||
},
|
||||
crate::entities::common::edit_prop(
|
||||
t!("Position X").as_ref(),
|
||||
PROP_POSITION_X,
|
||||
position.x,
|
||||
),
|
||||
crate::entities::common::edit_prop(
|
||||
t!("Position Y").as_ref(),
|
||||
PROP_POSITION_Y,
|
||||
position.y,
|
||||
),
|
||||
crate::entities::common::edit_prop(
|
||||
t!("Position Z").as_ref(),
|
||||
PROP_POSITION_Z,
|
||||
position.z,
|
||||
),
|
||||
Property {
|
||||
label: t!("Profile rotation").into_owned(),
|
||||
field: PROP_PROFILE_ROTATION,
|
||||
value: PropValue::EditText(
|
||||
crate::entities::common::format_angle(value.align_angle),
|
||||
),
|
||||
},
|
||||
Property {
|
||||
label: t!("Bank").into_owned(),
|
||||
field: PROP_BANK,
|
||||
value: PropValue::ReadOnly(
|
||||
if value.bank { "Yes" } else { "No" }.to_string(),
|
||||
),
|
||||
},
|
||||
Property {
|
||||
label: t!("Twist along path").into_owned(),
|
||||
field: PROP_TWIST_ALONG_PATH,
|
||||
value: PropValue::EditText(
|
||||
crate::entities::common::format_angle(value.twist_angle),
|
||||
),
|
||||
},
|
||||
Property {
|
||||
label: t!("Scale along path").into_owned(),
|
||||
field: PROP_SCALE_ALONG_PATH,
|
||||
value: PropValue::EditText(value.scale_factor.to_string()),
|
||||
},
|
||||
Property {
|
||||
label: t!("Length").into_owned(),
|
||||
field: PROP_SWEEP_LENGTH,
|
||||
value: PropValue::ReadOnly(length),
|
||||
},
|
||||
],
|
||||
},
|
||||
PropSection {
|
||||
@@ -185,20 +200,61 @@ fn sweep_properties(
|
||||
Property {
|
||||
label: t!("History").into_owned(),
|
||||
field: PROP_HISTORY,
|
||||
value: PropValue::ReadOnly(
|
||||
if record_history { "Record" } else { "None" }.to_string(),
|
||||
),
|
||||
value: PropValue::Choice {
|
||||
selected: if record_history { "Record" } else { "None" }.to_string(),
|
||||
options: vec!["None".to_string(), "Record".to_string()],
|
||||
},
|
||||
},
|
||||
Property {
|
||||
label: t!("Show History").into_owned(),
|
||||
field: PROP_SHOW_HISTORY,
|
||||
value: PropValue::ReadOnly(show_value.to_string()),
|
||||
value: if show_history_editable {
|
||||
PropValue::Choice {
|
||||
selected: show_value.to_string(),
|
||||
options: vec!["No".to_string(), "Yes".to_string()],
|
||||
}
|
||||
} else {
|
||||
PropValue::ReadOnly(show_value.to_string())
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
fn sweep_path_length(value: &SolidHistorySweep) -> Option<f64> {
|
||||
use acadrust::entities::EmbeddedEntity;
|
||||
use acadrust::EntityType;
|
||||
|
||||
let entity = match value.path_entity.as_ref()? {
|
||||
EmbeddedEntity::Line(value) => EntityType::Line(value.clone()),
|
||||
EmbeddedEntity::Arc(value) => EntityType::Arc(value.clone()),
|
||||
EmbeddedEntity::Circle(value) => EntityType::Circle(value.clone()),
|
||||
EmbeddedEntity::Ellipse(value) => EntityType::Ellipse(value.clone()),
|
||||
EmbeddedEntity::Spline(value) => EntityType::Spline(value.clone()),
|
||||
EmbeddedEntity::LwPolyline(value) => EntityType::LwPolyline(value.clone()),
|
||||
_ => return None,
|
||||
};
|
||||
let curve = crate::entities::curve::entity_curve(&entity)?;
|
||||
let transform = value.path_entity_transform;
|
||||
if transform.iter().any(|value| !value.is_finite())
|
||||
|| transform[3].abs() > 1e-9
|
||||
|| transform[7].abs() > 1e-9
|
||||
|| transform[11].abs() > 1e-9
|
||||
|| (transform[15] - 1.0).abs() > 1e-9
|
||||
{
|
||||
return None;
|
||||
}
|
||||
let placement = cadkernel::brep::Placement {
|
||||
x_axis: [transform[0], transform[1], transform[2]],
|
||||
y_axis: [transform[4], transform[5], transform[6]],
|
||||
z_axis: [transform[8], transform[9], transform[10]],
|
||||
origin: [transform[12], transform[13], transform[14]],
|
||||
};
|
||||
let length = curve.curve.length() * placement.scale()?;
|
||||
(length.is_finite() && length >= 0.0).then_some(length)
|
||||
}
|
||||
|
||||
fn torus_properties(
|
||||
document: &acadrust::CadDocument,
|
||||
handle: acadrust::Handle,
|
||||
@@ -860,6 +916,9 @@ pub fn is_primitive_property(field: &str) -> bool {
|
||||
| PROP_POSITION_Y
|
||||
| PROP_POSITION_Z
|
||||
| PROP_ROTATION
|
||||
| PROP_PROFILE_ROTATION
|
||||
| PROP_TWIST_ALONG_PATH
|
||||
| PROP_SCALE_ALONG_PATH
|
||||
| PROP_PYRAMID_TYPE
|
||||
)
|
||||
}
|
||||
@@ -868,6 +927,12 @@ pub fn is_history_choice(field: &str) -> bool {
|
||||
matches!(field, PROP_HISTORY | PROP_SHOW_HISTORY)
|
||||
}
|
||||
|
||||
pub fn is_specialized_property(field: &str) -> bool {
|
||||
matches!(field, "solid_history_type" | PROP_BANK | PROP_SWEEP_LENGTH)
|
||||
|| is_primitive_property(field)
|
||||
|| is_history_choice(field)
|
||||
}
|
||||
|
||||
pub fn apply_history_choice(
|
||||
document: &mut acadrust::CadDocument,
|
||||
handle: acadrust::Handle,
|
||||
@@ -1067,38 +1132,41 @@ fn apply_cylinder_position_property(
|
||||
Some(true)
|
||||
}
|
||||
|
||||
fn apply_sweep_position_property(
|
||||
fn apply_sweep_geometry_property(
|
||||
value: &mut SolidHistorySweep,
|
||||
field: &str,
|
||||
text: &str,
|
||||
) -> Option<bool> {
|
||||
let axis = match field {
|
||||
PROP_POSITION_X => 0,
|
||||
PROP_POSITION_Y => 1,
|
||||
PROP_POSITION_Z => 2,
|
||||
_ => return None,
|
||||
};
|
||||
let target = crate::entities::common::parse_length(text)?;
|
||||
if !target.is_finite() {
|
||||
return Some(false);
|
||||
match field {
|
||||
PROP_PROFILE_ROTATION => {
|
||||
let target = crate::entities::common::parse_angle(text)?;
|
||||
if !target.is_finite() || (target - value.align_angle).abs() <= 1e-12 {
|
||||
return Some(false);
|
||||
}
|
||||
value.align_angle = target;
|
||||
Some(true)
|
||||
}
|
||||
PROP_TWIST_ALONG_PATH => {
|
||||
let target = crate::entities::common::parse_angle(text)?;
|
||||
if !target.is_finite() || (target - value.twist_angle).abs() <= 1e-12 {
|
||||
return Some(false);
|
||||
}
|
||||
value.twist_angle = target;
|
||||
Some(true)
|
||||
}
|
||||
PROP_SCALE_ALONG_PATH => {
|
||||
let target = text.trim().replace(',', ".").parse::<f64>().ok()?;
|
||||
if !target.is_finite()
|
||||
|| target <= 1e-9
|
||||
|| (target - value.scale_factor).abs() <= 1e-12
|
||||
{
|
||||
return Some(false);
|
||||
}
|
||||
value.scale_factor = target;
|
||||
Some(true)
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
let current = matrix(value.base.transform)?;
|
||||
let reference = current.transform_point3(glam::DVec3::new(
|
||||
value.reference_point.x,
|
||||
value.reference_point.y,
|
||||
value.reference_point.z,
|
||||
));
|
||||
if !reference.is_finite() || (target - reference[axis]).abs() <= 1e-12 {
|
||||
return Some(false);
|
||||
}
|
||||
let mut delta = glam::DVec3::ZERO;
|
||||
delta[axis] = target - reference[axis];
|
||||
let updated = glam::DMat4::from_translation(delta) * current;
|
||||
if !updated.is_finite() || updated.determinant().abs() <= 1e-12 {
|
||||
return Some(false);
|
||||
}
|
||||
value.base.transform = updated.to_cols_array();
|
||||
Some(true)
|
||||
}
|
||||
|
||||
fn apply_torus_position_property(
|
||||
@@ -1290,7 +1358,7 @@ pub fn apply_primitive_property(
|
||||
}
|
||||
}
|
||||
if let SolidHistoryOperation::Sweep(sweep_value) = operation {
|
||||
if let Some(applied) = apply_sweep_position_property(sweep_value, field, value) {
|
||||
if let Some(applied) = apply_sweep_geometry_property(sweep_value, field, value) {
|
||||
return applied;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user