forked from 1b-agent/opencadstudio-upstream
feat(snap): independent 3D object-snap system with six modes
Grid snap locks to SNAPUNIT instead of magnetizing; snapped 3D points keep elevation instead of flattening to z=0. New SnapTypes Vertex/EdgeMidpoint/FaceCenter/Knot/FacePerpendicular/NearestFace with their own F4 master toggle and mode set, tiers, and markers, fully independent of the 2D master. Solid B-rep corners/edge-midpoints/face-centers from mesh edges and kernel faces, spline knot points, and live perpendicular/nearest-to-face on mesh triangles merged priority-aware in move/click paths. Drafting Settings 3D Object Snap tab is fully live (was dead placeholders); Nearest-to-face off by default. TDD: behavioral LINE-to-solid tests plus engine/scene unit tests.
This commit is contained in:
1 parent
d894b8eb05
commit
ca0ee37d26
16 files changed
+1728
-67
No files matched your search
@@ -1580,6 +1580,68 @@ impl canvas::Program<Message> for SelectionCanvas {
|
||||
frame.stroke(&h, stroke.clone());
|
||||
frame.stroke(&v, stroke);
|
||||
}
|
||||
SnapType::Vertex => {
|
||||
// Filled square: the solid rhyme of Endpoint's hollow box.
|
||||
let h = 5.0_f32;
|
||||
frame.fill(
|
||||
&canvas::Path::rectangle(
|
||||
Point::new(sp.x - h, sp.y - h),
|
||||
Size::new(h * 2.0, h * 2.0),
|
||||
),
|
||||
marker,
|
||||
);
|
||||
}
|
||||
SnapType::EdgeMidpoint => {
|
||||
// Filled triangle: the solid rhyme of Midpoint's outline.
|
||||
let r = 6.0_f32;
|
||||
let path = canvas::Path::new(|b| {
|
||||
b.move_to(Point::new(sp.x, sp.y - r));
|
||||
b.line_to(Point::new(sp.x + r * 0.866, sp.y + r * 0.5));
|
||||
b.line_to(Point::new(sp.x - r * 0.866, sp.y + r * 0.5));
|
||||
b.close();
|
||||
});
|
||||
frame.fill(&path, marker);
|
||||
}
|
||||
SnapType::FaceCenter => {
|
||||
// Filled disc: the solid rhyme of Center's outline.
|
||||
frame.fill(&canvas::Path::circle(sp, 5.5_f32), marker);
|
||||
}
|
||||
SnapType::Knot => {
|
||||
// Filled diamond: distinct from Quadrant's outline.
|
||||
let r = 5.5_f32;
|
||||
let path = canvas::Path::new(|b| {
|
||||
b.move_to(Point::new(sp.x, sp.y - r));
|
||||
b.line_to(Point::new(sp.x + r, sp.y));
|
||||
b.line_to(Point::new(sp.x, sp.y + r));
|
||||
b.line_to(Point::new(sp.x - r, sp.y));
|
||||
b.close();
|
||||
});
|
||||
frame.fill(&path, marker);
|
||||
}
|
||||
SnapType::FacePerpendicular => {
|
||||
// Right-angle hook like the 2D marker, plus a filled foot
|
||||
// dot marking the face contact.
|
||||
let r = 6.0_f32;
|
||||
let p = canvas::Path::new(|b| {
|
||||
b.move_to(Point::new(sp.x - r, sp.y - r));
|
||||
b.line_to(Point::new(sp.x - r, sp.y + r));
|
||||
b.line_to(Point::new(sp.x + r, sp.y + r));
|
||||
});
|
||||
frame.stroke(&p, stroke.clone());
|
||||
frame.fill(&canvas::Path::circle(sp, 2.0_f32), marker);
|
||||
}
|
||||
SnapType::NearestFace => {
|
||||
// Filled bowtie: the solid rhyme of Nearest's outline.
|
||||
let r = 5.5_f32;
|
||||
let path = canvas::Path::new(|b| {
|
||||
b.move_to(Point::new(sp.x - r, sp.y - r));
|
||||
b.line_to(Point::new(sp.x + r, sp.y - r));
|
||||
b.line_to(Point::new(sp.x - r, sp.y + r));
|
||||
b.line_to(Point::new(sp.x + r, sp.y + r));
|
||||
b.close();
|
||||
});
|
||||
frame.fill(&path, marker);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user