forked from 1b-agent/opencadstudio-upstream
Merge pull request #856 from ramox81/codex/align-circle-behavior
This commit is contained in:
commit
d9aead3fbc
12 files changed
+417
-172
No files matched your search
+59
-34
@@ -20,14 +20,15 @@ fn to_render(circle: &Circle) -> RenderEntity {
|
||||
let (ax, ay) = crate::scene::view::transform::ocs_axes(normal);
|
||||
let (cwx, cwy, cwz) = crate::scene::view::transform::ocs_point_to_wcs((cx, cy, cz), normal);
|
||||
|
||||
let rf = r as f32;
|
||||
// Centre and quadrants come from the entity's own curve, so the same
|
||||
// definition answers here, in the tessellation and in a trim.
|
||||
let curve = crate::entities::curve::circle_curve(circle);
|
||||
let snap_pts = crate::entities::curve::snap_from(&curve).snap_pts;
|
||||
let tangent = TangentGeom::Circle {
|
||||
center: [cwx as f32, cwy as f32, cwz as f32],
|
||||
radius: rf,
|
||||
let tangent = TangentGeom::PlanarCircle {
|
||||
center: [cwx, cwy, cwz],
|
||||
axis_x: [ax.0, ax.1, ax.2],
|
||||
axis_y: [ay.0, ay.1, ay.2],
|
||||
radius: r,
|
||||
};
|
||||
|
||||
if circle.thickness.abs() > 1e-10 {
|
||||
@@ -74,14 +75,7 @@ fn to_render(circle: &Circle) -> RenderEntity {
|
||||
};
|
||||
}
|
||||
|
||||
// Sampled from the entity's own curve rather than as a
|
||||
// `circle_arc` (arc-through-three-points). At large WCS coordinates
|
||||
// (e.g. −1.2M UTM) the three-point fit cancels catastrophically — the
|
||||
// circle comes back with a ~3% radius wobble and uneven segment lengths,
|
||||
// which then throws off a dashed linetype's dash spacing. Direct
|
||||
// evaluation only adds a small ±r term to the centre, so it stays
|
||||
// precise; the `Lines` path RTE-splits the absolute-f64 points into the
|
||||
// double-single the shader reconstructs.
|
||||
// Keep tessellation on the entity curve for large-coordinate precision.
|
||||
let pts = crate::entities::curve::curve_points(&curve);
|
||||
|
||||
RenderEntity {
|
||||
@@ -95,26 +89,31 @@ fn to_render(circle: &Circle) -> RenderEntity {
|
||||
}
|
||||
|
||||
fn grips(circle: &Circle) -> Vec<GripDef> {
|
||||
let ctr = glam::DVec3::new(circle.center.x, circle.center.y, circle.center.z);
|
||||
let center = circle.center_wcs();
|
||||
let (axis_x, axis_y) = circle.axes_wcs();
|
||||
let ctr = glam::DVec3::new(center.x, center.y, center.z);
|
||||
let axis_x = glam::DVec3::new(axis_x.x, axis_x.y, axis_x.z);
|
||||
let axis_y = glam::DVec3::new(axis_y.x, axis_y.y, axis_y.z);
|
||||
let r = circle.radius;
|
||||
vec![
|
||||
center_grip(0, ctr),
|
||||
square_grip(1, ctr + glam::DVec3::new(r, 0.0, 0.0)),
|
||||
square_grip(2, ctr + glam::DVec3::new(0.0, r, 0.0)),
|
||||
square_grip(3, ctr - glam::DVec3::new(r, 0.0, 0.0)),
|
||||
square_grip(4, ctr - glam::DVec3::new(0.0, r, 0.0)),
|
||||
square_grip(1, ctr + axis_x * r),
|
||||
square_grip(2, ctr + axis_y * r),
|
||||
square_grip(3, ctr - axis_x * r),
|
||||
square_grip(4, ctr - axis_y * r),
|
||||
]
|
||||
}
|
||||
|
||||
fn properties(circle: &Circle) -> Vec<PropSection> {
|
||||
use std::f64::consts::PI;
|
||||
let r = circle.radius;
|
||||
let center = circle.center_wcs();
|
||||
vec![PropSection {
|
||||
title: t!("Geometry").into_owned(),
|
||||
props: vec![
|
||||
edit(t!("Center X").as_ref(), "center_x", circle.center.x),
|
||||
edit(t!("Center Y").as_ref(), "center_y", circle.center.y),
|
||||
edit(t!("Center Z").as_ref(), "center_z", circle.center.z),
|
||||
edit(t!("Center X").as_ref(), "center_x", center.x),
|
||||
edit(t!("Center Y").as_ref(), "center_y", center.y),
|
||||
edit(t!("Center Z").as_ref(), "center_z", center.z),
|
||||
edit(t!("Radius").as_ref(), "radius", r),
|
||||
edit(t!("Diameter").as_ref(), "diameter", r * 2.0),
|
||||
edit(t!("Circumference").as_ref(), "circumference", 2.0 * PI * r),
|
||||
@@ -132,9 +131,22 @@ fn apply_geom_prop(circle: &mut Circle, field: &str, value: &str) {
|
||||
return;
|
||||
};
|
||||
match field {
|
||||
"center_x" => circle.center.x = v,
|
||||
"center_y" => circle.center.y = v,
|
||||
"center_z" => circle.center.z = v,
|
||||
"center_x" | "center_y" | "center_z" => {
|
||||
let normal = (circle.normal.x, circle.normal.y, circle.normal.z);
|
||||
let center = circle.center_wcs();
|
||||
let (mut x, mut y, mut z) = (center.x, center.y, center.z);
|
||||
match field {
|
||||
"center_x" => x = v,
|
||||
"center_y" => y = v,
|
||||
"center_z" => z = v,
|
||||
_ => {}
|
||||
}
|
||||
let (ox, oy, oz) =
|
||||
crate::scene::view::transform::wcs_point_to_ocs((x, y, z), normal);
|
||||
circle.center.x = ox;
|
||||
circle.center.y = oy;
|
||||
circle.center.z = oz;
|
||||
}
|
||||
"radius" if v > 0.0 => circle.radius = v,
|
||||
"diameter" if v > 0.0 => circle.radius = v / 2.0,
|
||||
"circumference" if v > 0.0 => circle.radius = v / (2.0 * PI),
|
||||
@@ -146,19 +158,31 @@ fn apply_geom_prop(circle: &mut Circle, field: &str, value: &str) {
|
||||
fn apply_grip(circle: &mut Circle, grip_id: usize, apply: GripApply) {
|
||||
match (grip_id, apply) {
|
||||
(0, GripApply::Absolute(p)) => {
|
||||
circle.center.x = p.x as f64;
|
||||
circle.center.y = p.y as f64;
|
||||
circle.center.z = p.z as f64;
|
||||
let (x, y, z) = crate::scene::view::transform::wcs_point_to_ocs(
|
||||
(p.x, p.y, p.z),
|
||||
(circle.normal.x, circle.normal.y, circle.normal.z),
|
||||
);
|
||||
circle.center.x = x;
|
||||
circle.center.y = y;
|
||||
circle.center.z = z;
|
||||
}
|
||||
(0, GripApply::Translate(d)) => {
|
||||
circle.center.x += d.x as f64;
|
||||
circle.center.y += d.y as f64;
|
||||
circle.center.z += d.z as f64;
|
||||
let (x, y, z) = crate::scene::view::transform::wcs_point_to_ocs(
|
||||
(d.x, d.y, d.z),
|
||||
(circle.normal.x, circle.normal.y, circle.normal.z),
|
||||
);
|
||||
circle.center.x += x;
|
||||
circle.center.y += y;
|
||||
circle.center.z += z;
|
||||
}
|
||||
(1..=4, GripApply::Absolute(p)) => {
|
||||
let dx = p.x - circle.center.x;
|
||||
let dy = p.y - circle.center.y;
|
||||
circle.radius = (dx * dx + dy * dy).sqrt();
|
||||
let plane = crate::entities::curve::circle_curve(circle).plane;
|
||||
if let Some(point) = plane.project([p.x, p.y, p.z]) {
|
||||
let radius = (point[0] - circle.center.x).hypot(point[1] - circle.center.y);
|
||||
if radius > 1.0e-9 {
|
||||
circle.radius = radius;
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
@@ -187,11 +211,12 @@ impl crate::entities::traits::MassPropsCalc for Circle {
|
||||
fn mass_props(&self) -> crate::entities::traits::MassProps {
|
||||
use std::f64::consts::{PI, TAU};
|
||||
let r = self.radius;
|
||||
let center = self.center_wcs();
|
||||
crate::entities::traits::MassProps {
|
||||
area: PI * r * r,
|
||||
perimeter: TAU * r,
|
||||
cx: self.center.x,
|
||||
cy: self.center.y,
|
||||
cx: center.x,
|
||||
cy: center.y,
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user