mirror of
https://github.com/bherbruck/solidcraft.git
synced 2026-11-05 11:35:55 +00:00
Bodies: an operation's result is its record, not the SMLib body it was exported from
A body made by an SMLib operation kept that SMLib body beside its record (SMLib's export). The export is not exact to the bit, so the kept body measured and operated a little differently from the record's import, which is what a body read back from a file has: a box measured 24000.000000000004 mm³ live and 24000.0 reopened, a drilled box 21989.38056 against 21989.38013. A cut ring's volume therefore changed when it was moved, the moved ring being measured on the SMLib body the move made (measure_centre_tests::combine_cut_volume_does_not_depend_on_placement). Every body now imports its record when an operation first needs it, so evaluated and reopened bodies are the same. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+11
-12
@@ -441,15 +441,11 @@ impl SurfaceKind {
|
||||
|
||||
impl Body {
|
||||
/// A body with `record` and nothing else set.
|
||||
fn bare(record: Brep, smlib: Option<solidcraft_smlib::Brep>, mesh: Option<std::sync::Arc<crate::meshbody::TriMesh>>) -> Body {
|
||||
fn bare(record: Brep, mesh: Option<std::sync::Arc<crate::meshbody::TriMesh>>) -> Body {
|
||||
let size = span_of(&record);
|
||||
let cell = std::sync::OnceLock::new();
|
||||
if let Some(handle) = smlib {
|
||||
let _ = cell.set(Ok(handle));
|
||||
}
|
||||
Body {
|
||||
record: std::sync::Arc::new(record),
|
||||
smlib: std::sync::Arc::new(cell),
|
||||
smlib: std::sync::Arc::new(std::sync::OnceLock::new()),
|
||||
size,
|
||||
volume: Some(std::sync::Arc::new(std::sync::Mutex::new(None))),
|
||||
mesh,
|
||||
@@ -468,18 +464,21 @@ impl Body {
|
||||
/// structure (budgets, references, loops, regions, canonical order). Its faces face as the
|
||||
/// record says.
|
||||
pub(crate) fn from_record(record: Brep) -> Result<Body> {
|
||||
Ok(Body::bare(solid_record(record)?, None, None))
|
||||
Ok(Body::bare(solid_record(record)?, None))
|
||||
}
|
||||
|
||||
/// The body of an SMLib B-rep and its record (SMLib's export, in canonical order), keeping
|
||||
/// the SMLib body so later operations need not build it again.
|
||||
pub(crate) fn from_smlib_record(handle: solidcraft_smlib::Brep, record: Brep) -> Result<Body> {
|
||||
Ok(Body::bare(solid_record(record)?, Some(handle), None))
|
||||
/// The body of SMLib's export of a B-rep (its record, in canonical order). The SMLib body
|
||||
/// the export came from is not kept: the export is not exact to the bit (its parameters,
|
||||
/// radians, pcurves), so that body measures and operates a little differently from the
|
||||
/// record's import, and a body evaluated afresh would then differ from the same body read
|
||||
/// back from a file. Every operation starts from the record's import ([`Body::smlib`]).
|
||||
pub(crate) fn from_smlib_record(record: Brep) -> Result<Body> {
|
||||
Ok(Body::bare(solid_record(record)?, None))
|
||||
}
|
||||
|
||||
/// A mesh body of `mesh`.
|
||||
pub(crate) fn of_mesh(mesh: crate::meshbody::TriMesh) -> Body {
|
||||
Body::bare(empty_record(), None, Some(std::sync::Arc::new(mesh)))
|
||||
Body::bare(empty_record(), Some(std::sync::Arc::new(mesh)))
|
||||
}
|
||||
|
||||
/// The body's record: faces, edges and vertices in the body's own order. Empty for a mesh body.
|
||||
|
||||
@@ -126,7 +126,7 @@ pub fn decode_native_body(bytes: &[u8]) -> Result<Body> {
|
||||
}
|
||||
|
||||
/// An SMLib body as a kernel body: SMLib's export mapped by `solidcraft_smlib` (canonical order,
|
||||
/// radians, pcurves) is the body's record, and the SMLib body is kept with it.
|
||||
/// radians, pcurves) is the body's record ([`Body::from_smlib_record`]).
|
||||
pub fn body_from_smlib(brep: &solidcraft_smlib::Brep) -> Result<Body> {
|
||||
let _span = solidcraft_profile::span("kernel", "body_from_smlib");
|
||||
body_from_smlib_ordered(brep).map(|(body, _)| body)
|
||||
@@ -137,8 +137,7 @@ pub fn body_from_smlib(brep: &solidcraft_smlib::Brep) -> Result<Body> {
|
||||
pub(crate) fn body_from_smlib_ordered(brep: &solidcraft_smlib::Brep) -> Result<(Body, Option<solidcraft_smlib::history::Order>)> {
|
||||
let _span = solidcraft_profile::span("kernel", "body_from_smlib_ordered");
|
||||
let (record, order) = brep.to_native_ordered().map_err(|e| KernelError::Failed(e.to_string()))?;
|
||||
let handle = brep.try_clone().map_err(|e| KernelError::Failed(format!("SMLib: {e}")))?;
|
||||
Ok((Body::from_smlib_record(handle, record)?, Some(order)))
|
||||
Ok((Body::from_smlib_record(record)?, Some(order)))
|
||||
}
|
||||
|
||||
/// `body` in SMLib, with where each of SMLib's faces and edges is in the body's face and edge
|
||||
|
||||
@@ -1255,7 +1255,7 @@ mod imp {
|
||||
checked(&sewn, "stitch")?;
|
||||
let (record, kept) = sewn.to_native_ordered().map_err(|e| failed(format!("SMLib stitch: {e}")))?;
|
||||
let h = if same_numbering(r, &back) { sewn.history().ok().and_then(|raw| raw.history(&[order], &kept).ok()) } else { None };
|
||||
Ok((Body::from_smlib_record(sewn, record)?, h))
|
||||
Ok((Body::from_smlib_record(record)?, h))
|
||||
}
|
||||
|
||||
pub(super) fn thicken(body: &Body, thickness: f64, symmetric: bool) -> Result<Body> {
|
||||
|
||||
Reference in New Issue
Block a user