forked from 1b-agent/opencadstudio-upstream
fix(properties): correct XLine geometry
Merge PR #806 and route point/direction math through the kernel so valid near-zero directions are not rejected by an application tolerance.
This commit is contained in:
commit
5d4a279c1d
2 files changed
+49
-11
No files matched your search
+22
-4
@@ -51,6 +51,27 @@ fn xyz(v: Vector3) -> [f64; 3] {
|
||||
[v.x, v.y, v.z]
|
||||
}
|
||||
|
||||
fn vector3(v: Vec3) -> Vector3 {
|
||||
Vector3::new(v.x, v.y, v.z)
|
||||
}
|
||||
|
||||
pub(crate) fn point_along(origin: Vector3, direction: Vector3, parameter: f64) -> Vector3 {
|
||||
vector3(Vec3::from(xyz(origin)) + Vec3::from(xyz(direction)) * parameter)
|
||||
}
|
||||
|
||||
pub(crate) fn unit_direction(from: Vector3, through: Vector3) -> Option<Vector3> {
|
||||
unit_vector3(Vec3::from(xyz(through)) - Vec3::from(xyz(from)))
|
||||
}
|
||||
|
||||
pub(crate) fn unit_vector(vector: Vector3) -> Option<Vector3> {
|
||||
unit_vector3(Vec3::from(xyz(vector)))
|
||||
}
|
||||
|
||||
fn unit_vector3(vector: Vec3) -> Option<Vector3> {
|
||||
let unit = vector.normalize()?;
|
||||
(unit.x.is_finite() && unit.y.is_finite() && unit.z.is_finite()).then(|| vector3(unit))
|
||||
}
|
||||
|
||||
/// How far a point may sit off a candidate plane and still be taken to lie on
|
||||
/// it.
|
||||
///
|
||||
@@ -394,10 +415,7 @@ fn is_default_normal(normal: Vector3) -> bool {
|
||||
/// store. Zero would make every axis collapse and put the whole entity at
|
||||
/// one point.
|
||||
fn normalized(normal: Vector3) -> Vector3 {
|
||||
match Vec3::from(xyz(normal)).normalize() {
|
||||
Some(unit) => Vector3::new(unit.x, unit.y, unit.z),
|
||||
None => Vector3::new(0.0, 0.0, 1.0),
|
||||
}
|
||||
unit_vector(normal).unwrap_or(Vector3::new(0.0, 0.0, 1.0))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
+27
-7
@@ -3,6 +3,7 @@ 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::traits::{Grippable, PropertyEditable, Transformable, RenderConvertible};
|
||||
use crate::scene::convert::acad_to_render::{RenderEntity, RenderObject};
|
||||
use crate::scene::model::object::{GripApply, GripDef, PropSection};
|
||||
@@ -229,12 +230,16 @@ impl Grippable for XLine {
|
||||
|
||||
impl PropertyEditable for XLine {
|
||||
fn geometry_properties(&self, _text_style_names: &[String]) -> Vec<PropSection> {
|
||||
let second_point = point_along(self.base_point, self.direction, 1.0);
|
||||
vec![PropSection {
|
||||
title: t!("Geometry").into_owned(),
|
||||
props: vec![
|
||||
edit(t!("Base X").as_ref(), "xl_bx", self.base_point.x),
|
||||
edit(t!("Base Y").as_ref(), "xl_by", self.base_point.y),
|
||||
edit(t!("Base Z").as_ref(), "xl_bz", self.base_point.z),
|
||||
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),
|
||||
@@ -250,14 +255,29 @@ impl PropertyEditable for XLine {
|
||||
"xl_bx" => self.base_point.x = v,
|
||||
"xl_by" => self.base_point.y = v,
|
||||
"xl_bz" => self.base_point.z = v,
|
||||
"xl_dx" => {
|
||||
self.direction.x = v;
|
||||
"xl_sx" | "xl_sy" | "xl_sz" => {
|
||||
let mut second_point = self.point_at(1.0);
|
||||
match field {
|
||||
"xl_sx" => second_point.x = v,
|
||||
"xl_sy" => second_point.y = v,
|
||||
"xl_sz" => second_point.z = v,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
if let Some(direction) = unit_direction(self.base_point, second_point) {
|
||||
self.direction = direction;
|
||||
}
|
||||
}
|
||||
"xl_dy" => {
|
||||
self.direction.y = v;
|
||||
}
|
||||
"xl_dz" => {
|
||||
self.direction.z = v;
|
||||
"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;
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user