`sketch.constraint.symmetry` (line), `parallel`, `perpendicular`, `collinear`, `tangent` and `coincident` (point on curve) now take `x` / `y` for the sketch's own axes, matching what `solid.revolve` means by lowercase x|y. A real curve with that id still wins. An axis becomes a linked construction line on it: a new `LinkSource::SketchAxis` resolved in sketch coordinates, so it stays on the sketch's axis on any plane, is shared by every constraint on that axis, is left out of profiles and is reported in `created`. Equal, concentric, midpoint and horizontal/vertical keep refusing axes, since the axis line's finite length or fixed direction would make them meaningless. Claude-Session: https://claude.ai/code/session_01YDDPmNdRoBgkHcLeUDKVfb Co-authored-by: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
722bd007c8
commit
0dee9deec1
5 files changed
+332
-17
No files matched your search
@@ -42,7 +42,7 @@ pub use curves::{
|
||||
pub use decompose::Budget;
|
||||
pub use dims::{DimFrame, DimLayout, chain_centres, default_text, dim_frame, dim_layout, encode_text};
|
||||
pub use freeform_offset::{FreeformOffset, OFFSET_TOLERANCE};
|
||||
pub use link::{Link, LinkGeom, LinkKind, LinkSource, MAX_LINK_ENTITIES};
|
||||
pub use link::{Link, LinkGeom, LinkKind, LinkSource, MAX_LINK_ENTITIES, SKETCH_AXIS_HALF, sketch_axis_geom};
|
||||
pub use model::{Constraint, ConstraintKind, Curve, CurveKind, MAX_CONSTRAINTS, MAX_CURVES, MAX_POINTS, SPoint, Sketch, SketchError, SketchView};
|
||||
pub use offset::OffsetChain;
|
||||
pub use offset_topology::{OffsetCreated, OffsetRole, OffsetRoleFlags, OffsetRoleKind, OffsetTopology};
|
||||
|
||||
@@ -55,6 +55,9 @@ pub enum LinkSource {
|
||||
Origin,
|
||||
/// An origin axis (`X`, `Y`, `Z`).
|
||||
Axis { name: String },
|
||||
/// One of the sketch's own axes (`x` or `y`): the line through the sketch origin along it,
|
||||
/// whatever plane the sketch is on (see [`sketch_axis_geom`]).
|
||||
SketchAxis { name: String },
|
||||
/// An origin plane (`XY`, `XZ`, `YZ`) or a construction plane (by name): its trace on the
|
||||
/// sketch plane.
|
||||
Plane { name: String },
|
||||
@@ -90,6 +93,7 @@ impl LinkSource {
|
||||
LinkSource::SketchPoint { point, .. } => format!("sketch point {point}"),
|
||||
LinkSource::Origin => "origin".into(),
|
||||
LinkSource::Axis { name } => format!("{name} axis"),
|
||||
LinkSource::SketchAxis { name } => format!("sketch {name} axis"),
|
||||
LinkSource::Plane { name } => format!("{name} plane"),
|
||||
LinkSource::OnSurface { curve, .. } => format!("{curve} on a face"),
|
||||
LinkSource::Intersection { a, b } => format!("intersection of {} and {}", a.describe(), b.describe()),
|
||||
@@ -100,6 +104,19 @@ impl LinkSource {
|
||||
}
|
||||
}
|
||||
|
||||
/// Half length of the line a sketch axis link produces.
|
||||
pub const SKETCH_AXIS_HALF: f64 = 100.0;
|
||||
|
||||
/// The geometry of sketch axis `name` (`x` or `y`, sketch coordinates); `None` for any other name.
|
||||
pub fn sketch_axis_geom(name: &str) -> Option<LinkGeom> {
|
||||
let u = match name {
|
||||
"x" => Vec2::X,
|
||||
"y" => Vec2::Y,
|
||||
_ => return None,
|
||||
};
|
||||
Some(LinkGeom::Line(Vec2::ZERO - u * SKETCH_AXIS_HALF, u * SKETCH_AXIS_HALF))
|
||||
}
|
||||
|
||||
/// One link and its state.
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct Link {
|
||||
@@ -417,6 +434,34 @@ impl Sketch {
|
||||
self.curves.get(ci).and_then(|c| c.link.as_deref()).and_then(|l| self.link(l)).is_some_and(|l| l.lost)
|
||||
}
|
||||
|
||||
/// The line of sketch axis `name` (`x` or `y`) when the sketch already has one (see
|
||||
/// [`Sketch::sketch_axis_line`]).
|
||||
pub fn sketch_axis_curve(&self, name: &str) -> Option<usize> {
|
||||
self.links
|
||||
.iter()
|
||||
.filter(|l| matches!(&l.source, LinkSource::SketchAxis { name: n } if n == name))
|
||||
.find_map(|l| self.link_curves(&l.id).into_iter().find(|c| matches!(self.curves.get(*c).map(|c| &c.kind), Some(CurveKind::Line { .. }))))
|
||||
}
|
||||
|
||||
/// The line of sketch axis `name` (`x` or `y`) that constraints can refer to: a linked
|
||||
/// construction line on the axis (it stays there and is left out of profiles), shared by
|
||||
/// every reference to that axis and added on first use. `None` when `name` is not a sketch
|
||||
/// axis.
|
||||
pub fn sketch_axis_line(&mut self, name: &str) -> Result<Option<usize>> {
|
||||
let Some(geom) = sketch_axis_geom(name) else { return Ok(None) };
|
||||
if let Some(c) = self.sketch_axis_curve(name) {
|
||||
return Ok(Some(c));
|
||||
}
|
||||
let id = self.add_link(LinkKind::Project, LinkSource::SketchAxis { name: name.into() }, &[geom])?;
|
||||
let curves = self.link_curves(&id);
|
||||
for c in &curves {
|
||||
if let Some(cu) = self.curves.get_mut(*c) {
|
||||
cu.construction = true;
|
||||
}
|
||||
}
|
||||
curves.first().copied().map(Some).ok_or_else(|| SketchError::Invalid(format!("sketch {name} axis")))
|
||||
}
|
||||
|
||||
/// Add linked geometry. Returns the link id; the new curve and point ids are
|
||||
/// [`Sketch::link_curves`] / [`Sketch::link_points`] of it.
|
||||
pub fn add_link(&mut self, kind: LinkKind, source: LinkSource, geom: &[LinkGeom]) -> Result<String> {
|
||||
|
||||
Reference in new issue
Block a user