Faces split on purpose stay split: the body remembers its Split Face lines, export and healing keep the pieces apart
Split Face records the new edges as polylines on the body (Body::split_lines); the document carries them through later features. STEP export no longer joins pieces of one surface across such a line, and healing (fillets, chamfers, booleans, shell, draft) no longer merges coplanar pieces there, while incidental pieces (boolean leftovers, seam halves) still merge as before. Tests: plane and cylinder splits keep their face count through a STEP round trip (and join without the record), a second split keeps both lines, and an engine test exports a split box after a fillet with 8 faces. Fixes #11 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RjGw4gA5ZvKrU8MQP6sBgT
This commit is contained in:
1 parent
0a1ab40ea0
commit
4c8f080691
12 files changed
+144
-19
No files matched your search
@@ -19,6 +19,9 @@ pub struct Body {
|
||||
pub(crate) color: Option<[f32; 3]>,
|
||||
/// Opacity and face colours for export (set by the document; operations drop it).
|
||||
pub(crate) paint: Option<std::sync::Arc<Paint>>,
|
||||
/// Lines the user split faces along (Split Face), as polylines: export keeps the faces on
|
||||
/// either side apart where it would otherwise join pieces of one surface.
|
||||
pub(crate) splits: Option<std::sync::Arc<Vec<Vec<Vec3>>>>,
|
||||
}
|
||||
|
||||
/// How a body looks beyond its colour, for export: its opacity and its faces' own colours.
|
||||
@@ -278,6 +281,7 @@ impl Body {
|
||||
}
|
||||
&& self.color == other.color
|
||||
&& self.paint == other.paint
|
||||
&& self.splits == other.splits
|
||||
}
|
||||
|
||||
pub(crate) fn new(solid: Solid) -> Result<Body> {
|
||||
@@ -302,7 +306,7 @@ impl Body {
|
||||
if v < 0.0 {
|
||||
solid.not();
|
||||
}
|
||||
Ok(Body { solid: std::sync::Arc::new(solid), mesh: None, color: None, paint: None })
|
||||
Ok(Body { solid: std::sync::Arc::new(solid), mesh: None, color: None, paint: None, splits: None })
|
||||
}
|
||||
|
||||
/// A deep copy of the solid that can be mutated without affecting other bodies.
|
||||
@@ -335,6 +339,21 @@ impl Body {
|
||||
self
|
||||
}
|
||||
|
||||
/// Lines faces were split along on purpose (Split Face), as polylines.
|
||||
pub fn split_lines(&self) -> Option<&std::sync::Arc<Vec<Vec<Vec3>>>> {
|
||||
self.splits.as_ref()
|
||||
}
|
||||
|
||||
pub(crate) fn split_keep(&self) -> &[Vec<Vec3>] {
|
||||
self.splits.as_ref().map(|l| l.as_slice()).unwrap_or(&[])
|
||||
}
|
||||
|
||||
/// The same body with the lines its faces were split along on purpose.
|
||||
pub fn with_split_lines(mut self, s: Option<std::sync::Arc<Vec<Vec<Vec3>>>>) -> Body {
|
||||
self.splits = s.filter(|l| !l.is_empty());
|
||||
self
|
||||
}
|
||||
|
||||
/// Opacity and face colours for export, if any.
|
||||
pub fn paint(&self) -> Option<&Paint> {
|
||||
self.paint.as_deref()
|
||||
|
||||
Reference in new issue
Block a user