Extend any surface: natural, tangent and curvature, up to a target (#760) (#1166)

Extend works on any surface: natural (continuing the face's own surface), tangent (G1 run-off) or curvature (G2 run-off), by a distance, up to a plane or face, or back to the surface's bounds, with neighbouring edges lengthened to meet. Untrim and Extend share face parameter-loop helpers. The new SurfaceExtend fields are noted under format 21. Closes #760.
This commit is contained in:
Irakli Kourtis authored and GitHub committed 2026-10-14 22:46:29 -04:00
1 parent 41f0c3d0c6
commit b4edf05373
18 files changed
+2271 -263

No files matched your search

+41 -1
View File
@@ -1137,11 +1137,20 @@ pub enum FeatureKind {
#[serde(default, skip_serializing_if = "Option::is_none")]
face: Option<Vec3>,
},
/// A planar surface body extended outward by `distance` past the edges through `edges`.
/// A surface body's boundary edges through `edges` extended outward: by `distance`, or up
/// to `up_to`; the surface continued (`mode` natural) or a run-off face along each edge
/// (tangent, curvature). `neighbours`: the edges next to an extended edge are lengthened to
/// meet it (else the extension's sides run square to the edge).
SurfaceExtend {
body: String,
edges: Vec<Vec3>,
distance: String,
#[serde(default, skip_serializing_if = "ExtendMode::is_natural")]
mode: ExtendMode,
#[serde(default, skip_serializing_if = "Option::is_none")]
up_to: Option<ExtendTo>,
#[serde(default = "yes", skip_serializing_if = "is_yes")]
neighbours: bool,
},
/// A surface body trimmed by a plane, or by a face of a body (`tool`), keeping the side of
/// `keep`.
@@ -1189,6 +1198,37 @@ pub enum FeatureKind {
},
}
/// How Extend continues a surface past its edges.
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum ExtendMode {
/// The surface itself, continued.
#[default]
Natural,
/// A ruled run-off in the surface's tangent plane (G1).
Tangent,
/// A run-off that keeps the surface's curvature across the edge (G2).
Curvature,
}
impl ExtendMode {
pub fn is_natural(&self) -> bool {
*self == ExtendMode::Natural
}
}
/// What Extend extends up to instead of a distance.
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum ExtendTo {
/// A plane.
Plane(PlaneRef),
/// The surface of a body's face (extended).
Face(FaceAt),
/// The surface's own bounds (natural only): a trim undone.
Bounds,
}
/// How a fillet's size is given.
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "snake_case")]