Fix XLine and wipeout properties

This commit is contained in:
ramox81 committed 2026-09-11 17:11:52 +03:00
1 parent 21e085db7e
commit 21a232ef8d
6 files changed
+104 -36

No files matched your search

+64 -10
View File
@@ -2,7 +2,10 @@ use acadrust::entities::{RasterImage, Wipeout};
use crate::t;
use crate::command::EntityTransform;
use crate::entities::common::{center_grip, edit_prop as edit, ro_prop as ro, square_grip};
use crate::entities::common::{
center_grip, edit_angle_prop as edit_angle, edit_prop as edit, parse_angle_deg, parse_f64,
ro_prop as ro, square_grip,
};
use crate::entities::text_support::{resolve_text_style, text_local_bounds};
use crate::entities::traits::{Grippable, PropertyEditable, Transformable, RenderConvertible};
use crate::scene::convert::acad_to_render::{GlyphRun, TextStroke, RenderEntity, RenderObject};
@@ -473,6 +476,10 @@ fn wipeout_boundary(wipeout: &Wipeout) -> Vec<[f64; 3]> {
}
}
fn wipeout_axis_length(axis: &acadrust::types::Vector3, size: f64) -> f64 {
(axis.x * axis.x + axis.y * axis.y + axis.z * axis.z).sqrt() * size.abs()
}
fn wipeout_pick_rings(wipeout: &Wipeout) -> Vec<Vec<[f64; 3]>> {
let boundary = wipeout_boundary(wipeout);
if wipeout_is_polygonal(wipeout)
@@ -672,13 +679,28 @@ impl PropertyEditable for Wipeout {
let bg_transparency = self
.flags
.contains(acadrust::entities::WipeoutDisplayFlags::TRANSPARENCY_ON);
let width = wipeout_axis_length(&self.u_vector, self.size.x);
let height = wipeout_axis_length(&self.v_vector, self.size.y);
let rotation = self.u_vector.y.atan2(self.u_vector.x).to_degrees();
vec![
PropSection {
title: t!("Image Adjust").into_owned(),
props: vec![
ro(t!("Brightness").as_ref(), "wo_brightness", self.brightness.to_string()),
ro(t!("Contrast").as_ref(), "wo_contrast", self.contrast.to_string()),
ro(t!("Fade").as_ref(), "wo_fade", self.fade.to_string()),
],
},
PropSection {
title: t!("Geometry").into_owned(),
props: vec![
edit(t!("Position X").as_ref(), "wo_ox", self.insertion_point.x),
edit(t!("Position Y").as_ref(), "wo_oy", self.insertion_point.y),
edit(t!("Position Z").as_ref(), "wo_oz", self.insertion_point.z),
edit_angle(t!("Rotation").as_ref(), "wo_rotation", rotation),
edit(t!("Width").as_ref(), "wo_width", width),
edit(t!("Height").as_ref(), "wo_height", height),
ro(t!("Scale").as_ref(), "wo_scale", "1"),
],
},
PropSection {
@@ -689,25 +711,57 @@ impl PropertyEditable for Wipeout {
ro(t!("Background transparency").as_ref(), "wo_bg_transparency", if bg_transparency { t!("Yes") } else { t!("No") }),
],
},
PropSection {
title: t!("Image Adjust").into_owned(),
props: vec![
ro(t!("Brightness").as_ref(), "wo_brightness", self.brightness.to_string()),
ro(t!("Contrast").as_ref(), "wo_contrast", self.contrast.to_string()),
ro(t!("Fade").as_ref(), "wo_fade", self.fade.to_string()),
],
},
]
}
fn apply_geom_prop(&mut self, field: &str, value: &str) {
let Ok(v) = value.trim().parse::<f64>() else {
if field == "wo_rotation" {
let Some(target_degrees) = parse_angle_deg(value).filter(|value| value.is_finite()) else {
return;
};
let u = glam::DVec3::new(self.u_vector.x, self.u_vector.y, self.u_vector.z);
let v = glam::DVec3::new(self.v_vector.x, self.v_vector.y, self.v_vector.z);
let normal = u.cross(v).normalize_or_zero();
if normal.length_squared() <= 1e-18 {
return;
}
let current_radians = u.y.atan2(u.x);
let rotation = glam::DQuat::from_axis_angle(
normal,
target_degrees.to_radians() - current_radians,
);
let u = rotation * u;
let v = rotation * v;
self.u_vector = acadrust::types::Vector3::new(u.x, u.y, u.z);
self.v_vector = acadrust::types::Vector3::new(v.x, v.y, v.z);
return;
}
let Some(v) = parse_f64(value).filter(|value| value.is_finite()) else {
return;
};
match field {
"wo_ox" => self.insertion_point.x = v,
"wo_oy" => self.insertion_point.y = v,
"wo_oz" => self.insertion_point.z = v,
"wo_width" if v > 0.0 => {
let current = wipeout_axis_length(&self.u_vector, self.size.x);
if current > 1e-9 {
let scale = v / current;
self.u_vector.x *= scale;
self.u_vector.y *= scale;
self.u_vector.z *= scale;
}
}
"wo_height" if v > 0.0 => {
let current = wipeout_axis_length(&self.v_vector, self.size.y);
if current > 1e-9 {
let scale = v / current;
self.v_vector.x *= scale;
self.v_vector.y *= scale;
self.v_vector.z *= scale;
}
}
_ => {}
}
}
+19 -17
View File
@@ -2,8 +2,10 @@ use acadrust::entities::{Ray, XLine};
use crate::t;
use crate::command::EntityTransform;
use crate::entities::common::{center_grip, edit_prop as edit, square_grip};
use crate::entities::curve::{point_along, unit_direction, unit_vector};
use crate::entities::common::{
center_grip, edit_prop as edit, format_length, ro_prop as ro, square_grip,
};
use crate::entities::curve::{point_along, unit_direction};
use crate::entities::traits::{Grippable, PropertyEditable, Transformable, RenderConvertible};
use crate::scene::convert::acad_to_render::{RenderEntity, RenderObject};
use crate::scene::model::object::{GripApply, GripDef, PropSection};
@@ -240,9 +242,21 @@ impl PropertyEditable for XLine {
edit(t!("Second X").as_ref(), "xl_sx", second_point.x),
edit(t!("Second Y").as_ref(), "xl_sy", second_point.y),
edit(t!("Second Z").as_ref(), "xl_sz", second_point.z),
edit(t!("Direction vector X").as_ref(), "xl_dx", self.direction.x),
edit(t!("Direction vector Y").as_ref(), "xl_dy", self.direction.y),
edit(t!("Direction vector Z").as_ref(), "xl_dz", self.direction.z),
ro(
t!("Direction vector X").as_ref(),
"xl_dx",
format_length(self.direction.x),
),
ro(
t!("Direction vector Y").as_ref(),
"xl_dy",
format_length(self.direction.y),
),
ro(
t!("Direction vector Z").as_ref(),
"xl_dz",
format_length(self.direction.z),
),
],
}]
}
@@ -267,18 +281,6 @@ impl PropertyEditable for XLine {
self.direction = direction;
}
}
"xl_dx" | "xl_dy" | "xl_dz" => {
let mut direction = self.direction;
match field {
"xl_dx" => direction.x = v,
"xl_dy" => direction.y = v,
"xl_dz" => direction.z = v,
_ => unreachable!(),
}
if let Some(direction) = unit_vector(direction) {
self.direction = direction;
}
}
_ => {}
}
}
+13 -9
View File
@@ -335,7 +335,7 @@ impl CadCommand for WipeoutCommand {
let mut preview = self.points.clone();
preview.push(point);
preview.push(first);
Some(WireModel::solid_f64(
let mut wire = WireModel::solid_f64(
"wipeout_preview".into(),
preview
.iter()
@@ -343,7 +343,9 @@ impl CadCommand for WipeoutCommand {
.collect(),
WireModel::CYAN,
false,
))
);
wire.line_weight_px = 1.5;
Some(wire)
}
WipeoutMode::Rectangular => {
let first = self.first?;
@@ -359,12 +361,14 @@ impl CadCommand for WipeoutCommand {
]
.map(|corner| self.plane.to_world(corner))
};
Some(WireModel::solid_f64(
let mut wire = WireModel::solid_f64(
"wipeout_preview".into(),
corners.iter().map(|p| [p.x, p.y, p.z]).collect(),
WireModel::CYAN,
false,
))
);
wire.line_weight_px = 1.5;
Some(wire)
}
WipeoutMode::Polyline | WipeoutMode::Frames | WipeoutMode::ErasePolyline => None,
}
@@ -409,11 +413,11 @@ fn make_rect_wipeout(first: DVec3, second: DVec3, plane: Plane) -> Option<Entity
fn make_poly_wipeout(points: &[[f64; 2]], plane: Plane) -> Option<EntityType> {
plane.normal()?;
let frame = polygon_frame(points, Tolerance::default())?;
let [width, height] = frame.size;
let extent = frame.size[0].max(frame.size[1]);
let mut wipeout = Wipeout::new();
wipeout.insertion_point = vector(plane.point_at(frame.origin));
wipeout.u_vector = vector(plane.x_axis) * width;
wipeout.v_vector = vector(plane.y_axis) * height;
wipeout.u_vector = vector(plane.x_axis) * extent;
wipeout.v_vector = vector(plane.y_axis) * extent;
wipeout.size = Vector2::new(1.0, 1.0);
wipeout.clip_type = WipeoutClipType::Polygonal;
wipeout.clip_boundary_vertices = frame
@@ -421,8 +425,8 @@ fn make_poly_wipeout(points: &[[f64; 2]], plane: Plane) -> Option<EntityType> {
.iter()
.map(|point| {
Vector2::new(
(point[0] - frame.origin[0]) / width - 0.5,
0.5 - (point[1] - frame.origin[1]) / height,
(point[0] - frame.origin[0]) / extent - 0.5,
0.5 - (point[1] - frame.origin[1]) / extent,
)
})
.collect();
+1
View File
@@ -120,6 +120,7 @@ pub fn visualization_section(entity: &EntityType) -> Option<PropSection> {
| EntityType::BlockEnd(_)
| EntityType::Seqend(_)
| EntityType::Leader(_)
| EntityType::Wipeout(_)
| EntityType::Unknown(_)
// Non-plotting drawing-view border: never rendered, no properties.
| EntityType::ViewBorder(_)
+1
View File
@@ -1282,6 +1282,7 @@ fn tessellate_entity_inner(
}
if matches!(e, EntityType::Wipeout(_)) {
b.depth_override = Some(0.5);
b.line_weight_px = b.line_weight_px.max(1.5);
}
}
+6
View File
@@ -1609,6 +1609,12 @@ pub fn primitive_properties(
document: &acadrust::CadDocument,
handle: acadrust::Handle,
) -> Vec<PropSection> {
if !matches!(
document.get_entity(handle),
Some(acadrust::EntityType::Solid3D(_) | acadrust::EntityType::Surface(_))
) {
return Vec::new();
}
let Some(operation) = primitive_property_operation(document, handle) else {
return brep_properties(document, handle);
};