forked from 1b-agent/opencadstudio-upstream
Feat: ROADMAP Phase 1-5 batch — trim/extend, plot scale, viewport UX, mline caps, table alignment
- TRIM/EXTEND: Ray and XLine entities supported as cutting boundaries and trim targets; trim results in Ray→Line/Ray, XLine→Ray/Ray or Line; hover preview added - Plot scale override: Fit/1:1/1:2/1:5/1:10/1:20/1:50/1:100/2:1 buttons added to Page Setup panel; PageSetupCommit applies scale to PlotSettings - Viewport UX: locked viewport gets orange border; selected viewport gets white border - Named view → viewport assignment: Choice dropdown in properties panel copies view_target/direction/height to the viewport entity - MLine caps: perpendicular start/end cap lines added for open (non-closed) MLines - Wipeout polygon grips: boundary vertices become editable grips when clipping_enabled+Polygonal; world→pixel back-projection on drag - Table cell alignment: CellStyle.alignment (1-9) drives left/center/right + top/middle/bottom text positioning; cxf::measure_text() helper added - New commands/features: DIMCONTINUE (DCO), DIMBASELINE (DBA), TOLERANCE (TOL), TABLE, ATTDEF, ATTEDIT, ATTDISP, BREAKATPOINT (BAP), PLOTWINDOW (PW), MLINE (ML); DIMSTYLE/DIMCURRENT/CLAYER/LTSCALE/CELTSCALE/SCALETEXT/XDATA/UCSICON/REGEN/DRAWORDER extended - PLINE arc mode: A/L/CLOSE text input, bulge computation, arc preview - Warning cleanup: removed unused imports and unreachable patterns Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
27b5e124c7
commit
0aef1fc12f
27 files changed
+2217
-100
No files matched your search
@@ -251,23 +251,91 @@ impl TruckConvertible for Wipeout {
|
||||
|
||||
impl Grippable for Wipeout {
|
||||
fn grips(&self) -> Vec<GripDef> {
|
||||
let corners = image_corners(
|
||||
&self.insertion_point,
|
||||
&self.u_vector,
|
||||
&self.v_vector,
|
||||
self.size.x,
|
||||
self.size.y,
|
||||
);
|
||||
vec![
|
||||
square_grip(0, Vec3::from(corners[0])),
|
||||
diamond_grip(1, Vec3::from(corners[1])),
|
||||
diamond_grip(2, Vec3::from(corners[2])),
|
||||
diamond_grip(3, Vec3::from(corners[3])),
|
||||
]
|
||||
// If polygonal clipping is active, expose individual polygon vertices as grips.
|
||||
let is_polygon = self.clipping_enabled
|
||||
&& self.clip_boundary_vertices.len() >= 3
|
||||
&& matches!(
|
||||
self.clip_type,
|
||||
acadrust::entities::WipeoutClipType::Polygonal
|
||||
);
|
||||
|
||||
if is_polygon {
|
||||
let ox = self.insertion_point.x as f32;
|
||||
let oy = self.insertion_point.y as f32;
|
||||
let oz = self.insertion_point.z as f32;
|
||||
self.clip_boundary_vertices
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, v)| {
|
||||
let wx = (self.u_vector.x * v.x * self.size.x
|
||||
+ self.v_vector.x * v.y * self.size.y) as f32;
|
||||
let wy = (self.u_vector.y * v.x * self.size.x
|
||||
+ self.v_vector.y * v.y * self.size.y) as f32;
|
||||
let wz = (self.u_vector.z * v.x * self.size.x
|
||||
+ self.v_vector.z * v.y * self.size.y) as f32;
|
||||
if i == 0 {
|
||||
square_grip(i, Vec3::new(ox + wx, oy + wy, oz + wz))
|
||||
} else {
|
||||
diamond_grip(i, Vec3::new(ox + wx, oy + wy, oz + wz))
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
} else {
|
||||
let corners = image_corners(
|
||||
&self.insertion_point,
|
||||
&self.u_vector,
|
||||
&self.v_vector,
|
||||
self.size.x,
|
||||
self.size.y,
|
||||
);
|
||||
vec![
|
||||
square_grip(0, Vec3::from(corners[0])),
|
||||
diamond_grip(1, Vec3::from(corners[1])),
|
||||
diamond_grip(2, Vec3::from(corners[2])),
|
||||
diamond_grip(3, Vec3::from(corners[3])),
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
fn apply_grip(&mut self, grip_id: usize, apply: GripApply) {
|
||||
if grip_id == 0 {
|
||||
let is_polygon = self.clipping_enabled
|
||||
&& self.clip_boundary_vertices.len() >= 3
|
||||
&& matches!(
|
||||
self.clip_type,
|
||||
acadrust::entities::WipeoutClipType::Polygonal
|
||||
);
|
||||
|
||||
if is_polygon {
|
||||
// Move the clicked polygon vertex in world space → back-project to pixel space.
|
||||
if let Some(v) = self.clip_boundary_vertices.get_mut(grip_id) {
|
||||
// Compute current world position of this vertex.
|
||||
let ox = self.insertion_point.x;
|
||||
let oy = self.insertion_point.y;
|
||||
let oz = self.insertion_point.z;
|
||||
let cur_wx = ox + self.u_vector.x * v.x * self.size.x + self.v_vector.x * v.y * self.size.y;
|
||||
let cur_wy = oy + self.u_vector.y * v.x * self.size.x + self.v_vector.y * v.y * self.size.y;
|
||||
let cur_wz = oz + self.u_vector.z * v.x * self.size.x + self.v_vector.z * v.y * self.size.y;
|
||||
let new_w = match apply {
|
||||
GripApply::Translate(d) => {
|
||||
[cur_wx + d.x as f64, cur_wy + d.y as f64, cur_wz + d.z as f64]
|
||||
}
|
||||
GripApply::Absolute(p) => [p.x as f64, p.y as f64, p.z as f64],
|
||||
};
|
||||
// Back-project: solve for pixel coords using u_vector and v_vector.
|
||||
// In 2D (XY plane): new_w - insertion_point = u_vec * vx * sx + v_vec * vy * sy
|
||||
let dx = new_w[0] - self.insertion_point.x;
|
||||
let dy = new_w[1] - self.insertion_point.y;
|
||||
let ux = self.u_vector.x * self.size.x;
|
||||
let uy = self.u_vector.y * self.size.x;
|
||||
let vx = self.v_vector.x * self.size.y;
|
||||
let vy = self.v_vector.y * self.size.y;
|
||||
let det = ux * vy - uy * vx;
|
||||
if det.abs() > 1e-12 {
|
||||
v.x = (dx * vy - dy * vx) / det;
|
||||
v.y = (ux * dy - uy * dx) / det;
|
||||
}
|
||||
}
|
||||
} else if grip_id == 0 {
|
||||
match apply {
|
||||
GripApply::Translate(d) => {
|
||||
self.insertion_point.x += d.x as f64;
|
||||
|
||||
Reference in new issue
Block a user