Open large designs faster: move bodies into components without copying the model (#915)
A body transfer works out the moved bodies first and puts them in place in the evaluator's own copy of the model, instead of copying every body of the model for each transfer.
This commit is contained in:
1 parent
6c61442bb2
commit
c616f50bd0
1 file changed
+12
-7
@@ -31,11 +31,14 @@ pub fn validate_body_transfer(doc: &Document, bodies: &[String], from: u64, to:
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Moves the bodies in `st`, which the evaluator discards when this fails (so it is changed in
|
||||
/// place rather than copied: a copy of every body for each moved one was most of the cost).
|
||||
pub(crate) fn evaluate(doc: &Document, st: &mut ModelState, bodies: &[String], from: u64, to: u64, transform: Mat) -> Result<()> {
|
||||
validate_body_transfer(doc, bodies, from, to, &transform)?;
|
||||
let mut next = st.clone();
|
||||
let mut moved = Vec::with_capacity(bodies.len());
|
||||
for name in bodies {
|
||||
let old = st.body(name).ok_or_else(|| DocError::Unknown(format!("transferred body `{name}`")))?;
|
||||
let (slot, old) =
|
||||
st.bodies.iter().enumerate().find(|(_, b)| b.name == *name).ok_or_else(|| DocError::Unknown(format!("transferred body `{name}`")))?;
|
||||
if doc.model_body_component(old) != from {
|
||||
return Err(DocError::Invalid(format!("body `{name}` no longer belongs to transfer source component {from}")));
|
||||
}
|
||||
@@ -47,12 +50,14 @@ pub(crate) fn evaluate(doc: &Document, st: &mut ModelState, bodies: &[String], f
|
||||
body.source_transform = crate::mat_mul(&transform, &old.source_transform);
|
||||
body.imported = old.imported.clone();
|
||||
body.names = crate::naming::NameCell::same(old);
|
||||
let slot = next.bodies.iter_mut().find(|b| b.name == *name).ok_or_else(|| DocError::Unknown(format!("transferred body `{name}`")))?;
|
||||
*slot = body;
|
||||
moved.push((slot, body));
|
||||
}
|
||||
crate::body_transfer_sheet::remap_sheet_metadata(&mut next, bodies, &transform)?;
|
||||
*st = next;
|
||||
Ok(())
|
||||
for (slot, body) in moved {
|
||||
if let Some(b) = st.bodies.get_mut(slot) {
|
||||
*b = body;
|
||||
}
|
||||
}
|
||||
crate::body_transfer_sheet::remap_sheet_metadata(st, bodies, &transform)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
Reference in new issue
Block a user