Motion analysis: plots of a study's joint values and a point's path, and the parts that collide along it

- motion.plot: joint values and a point's path sampled as the study plays (closed loops
  following), with velocities and accelerations by finite differences, per step or per
  second with a duration.
- motion.interference: the pairs of parts that pass through each other along a study, with
  the first step, the step ranges, the depth and the shared volume; occurrences, against
  or contact sets choose the pairs; bounded samples and work.
- Motion Study dialog: a Study box opens a saved study; a chart of a joint value or a
  picked point with a cursor at the step shown (click to move there); Check collisions
  with the steps shaded on the chart. ui.start motion.study takes study.
This commit is contained in:
MateuszSychXpl committed 2026-10-16 17:52:38 +02:00
1 parent 8a055afdd6
commit 8fdf6a61a2
23 files changed
+1398 -40

No files matched your search

+10 -5
View File
@@ -71,11 +71,7 @@ pub(super) fn placement(s: &Session, inputs: &[SelInput]) -> Option<(Vec<u64>, V
/// The trace's parameters (OK's `motion.trace.keep` and the preview's `motion.trace`).
pub fn params(s: &Session, f: &TraceForm, inputs: &[SelInput]) -> Result<Value, String> {
let (path, at, shown, placed) = placement(s, inputs).ok_or("select a point on a component")?;
// The trace starts where the part is placed, not where it may be shown.
let at = mat_inverse(&shown).map(|m| apply_point(&placed, apply_point(&m, at))).ok_or("select a point on a component")?;
let occurrence = if path.is_empty() { json!(0) } else { json!(path) };
let mut p = json!({"occurrence": occurrence, "point": pt(at)});
let mut p = picked_point(s, inputs)?;
if f.by_study {
p["study"] = json!(s.doc.assembly.studies.get(f.study).ok_or("no motion study yet")?.id);
} else {
@@ -91,6 +87,15 @@ pub fn params(s: &Session, f: &TraceForm, inputs: &[SelInput]) -> Result<Value,
Ok(p)
}
/// The picked point as `motion.trace` and `motion.plot` take it: `{occurrence, point}`.
pub fn picked_point(s: &Session, inputs: &[SelInput]) -> Result<Value, String> {
let (path, at, shown, placed) = placement(s, inputs).ok_or("select a point on a component")?;
// The point starts where the part is placed, not where it may be shown.
let at = mat_inverse(&shown).map(|m| apply_point(&placed, apply_point(&m, at))).ok_or("select a point on a component")?;
let occurrence = if path.is_empty() { json!(0) } else { json!(path) };
Ok(json!({"occurrence": occurrence, "point": pt(at)}))
}
/// Where and why the motion stopped short, ending the trace (`None`: it went all the way).
fn stop_text(v: &Value) -> Option<String> {
let at = v["stopped_at"].as_u64()?.to_string();