Merge pull request #1712 from SychPL/feat/motion-analysis
Motion analysis: chart a study's joints and points, and find the parts that collide along it
This commit is contained in:
23 files changed
+1588
-51
No files matched your search
@@ -166,6 +166,39 @@ changed. A GIF keeps one palette for all its frames, so colours don't flicker, a
|
||||
what changed from one frame to the next. Frames are capped: at most 1000, and a GIF holds at most
|
||||
2^26 pixels of frames (about 160 frames of 800 × 500).
|
||||
|
||||
**Motion analysis.** The **Motion Study** dialog's **Study** box opens a saved study to edit, and
|
||||
by its timeline the dialog charts what the study does.
|
||||
**Plot** picks a moving joint value (a joint picked in the Browser is picked here too), or
|
||||
**Picked point** once a point is picked in the dialog's **Point** box, and **Quantity** whether to
|
||||
show its value, velocity or acceleration; the chart runs over the
|
||||
study's steps with a cursor at the step shown, and a click or a drag on it moves to that step.
|
||||
Values are in degrees and millimetres; rates are per step, or per second once **Duration** says
|
||||
how many seconds the whole study takes. A picked point charts its distance from where it
|
||||
starts, its speed and the size of its acceleration. **Check collisions** plays the study and
|
||||
lists the pairs of parts that pass through each other, with the steps where they do (a click on
|
||||
one shows the first of them); those steps are shaded on the chart. It checks the parts picked in
|
||||
**Components** (against the ones picked in **Against**, when there are any), else every
|
||||
component, or the pairs of the design's contact sets (a choice beside the button once it has any).
|
||||
|
||||
`motion.plot {study, joints?, occurrence?, point?, samples?, duration?}` answers the same
|
||||
numbers: for each joint value its `value`, `velocity` and `acceleration` per sample (with their
|
||||
units), and for a point its `position`, `velocity` and `acceleration` vectors, `speed` and
|
||||
`acceleration_norm`. The study plays as `motion.play` places it (closed loops follow, contact sets
|
||||
stop it), each sample from the one before, on a copy: the design is not changed. Velocities and
|
||||
accelerations are finite differences between samples, central inside and one-sided at the ends,
|
||||
so they are as smooth as the samples are dense (up to 1000, one per step by default). Angles are
|
||||
unwrapped, so a joint that turns on past half a turn keeps counting.
|
||||
`motion.interference {study, occurrences?, against?, contact_sets?, samples?}` answers each
|
||||
colliding pair with its `first_step`, `last_step`, the `steps` ranges where they overlap, how
|
||||
far into each other (`depth_mm`, the most at `deepest_step`) and their shared `volume_mm3`
|
||||
there (null when it is not cheap to work out). It plays the study as `motion.play` does, but
|
||||
contact sets don't stop it, and parts are tested at the samples only: a part that passes right
|
||||
through another between two samples is missed. Parts are told apart by occurrence, as contact
|
||||
sets tell them apart: an occurrence inside a sub-assembly placed twice is one part, so its two
|
||||
copies are not checked against each other. A check takes at most 256 bodies; on a large design,
|
||||
list the `occurrences` to check (an arm, with `against` the parts it must miss). When the work
|
||||
runs out it says `truncated` and the step it `checked_to`.
|
||||
|
||||
**Insert Design** (`component.insert_design {path, translate?}`, on the **ASSEMBLE** panel and
|
||||
in the **File** menu) adds a component linked to another saved design, so each part can live in
|
||||
its own document. A STEP or mesh file picked there is inserted as **Insert STEP** or **Insert
|
||||
|
||||
@@ -125,7 +125,7 @@ labels; `prefs:measure_axis_distances` identifies the checkbox.
|
||||
| `ui.set` | any `UiState` field (`tab`, `perspective`, `showGrid`, `dark`, …), and `hiddenBodies`, `hiddenOrigin`, `hiddenSketches`, `shownSketches`, `hiddenJoints` (whole lists; `browser.visibility` changes single items) | `dark: false` switches to the light theme |
|
||||
| `ui.view` | `view`: `front`, `back`, `top`, `bottom`, `left`, `right`, `iso`, `home`, `fit`; `animate` (bool, default false: snap) | |
|
||||
| `ui.camera` | `target?`: `[x, y, z]` (mm), `yaw?`, `pitch?`, `roll?` (radians), `distance?` (mm), `fov?`, `up?`; `fit?`: `true`, `false` or `[occurrence id or name…]` (`root`: the bodies outside every component) | the viewport's orbit camera: it looks at `target` from `distance` away; `yaw` 0 looks along +Y (from the front), `pitch` is the elevation (±π/2: straight down or up), `roll` turns the image. Fields given are set first (the others keep their values), then `fit` frames the listed occurrences (or everything), keeping the direction. The reply, passed back, sets the same view again, so a framing can be stored and replayed. `fov` and `up` follow the perspective setting (`ui.set`) and the up axis preference (`ui.prefs`) and can't change here; a refused field changes nothing |
|
||||
| `ui.start` | `command`, `params?` | like a toolbar click: starts the sketch tool or dialog for the command. `params` sets what the dialog opens on, and nothing runs until OK: `joint.drive` takes `joint` (id or name; without it, the joint picked in the browser, else the first joint that moves) and `values` (numbers in degrees or millimetres, or expressions). A command that takes no params is refused before it starts; a param the dialog doesn't take is refused and the dialog closes |
|
||||
| `ui.start` | `command`, `params?` | like a toolbar click: starts the sketch tool or dialog for the command. `params` sets what the dialog opens on, and nothing runs until OK: `joint.drive` takes `joint` (id or name; without it, the joint picked in the browser, else the first joint that moves) and `values` (numbers in degrees or millimetres, or expressions); `motion.study` takes `study` (id or name), which opens that study to edit and chart. A command that takes no params is refused before it starts; a param the dialog doesn't take is refused and the dialog closes |
|
||||
| `ui.click` | `x`, `y` (screen points), `button?`: left/right/middle, `shift?`, `ctrl?`, `double?` | real pointer input |
|
||||
| `ui.move` | `x`, `y`, `shift?`, `alt?`, `ctrl?`, `cmd?` | pointer movement without a button; modifiers apply until the next synthetic move/click; a move with omitted modifiers releases them. With `nav: "touchpad"`, Shift pans and Alt/Option orbits. |
|
||||
| `ui.drag` | `x0`, `y0`, `x1`, `y1`, `button?`, `shift?`, `ctrl?`, `steps?`, `hold?`, `hold_end?` | press, move, release; a left drag on the model is a box selection (left to right: window, right to left: crossing); with OpenSCAD navigation, plain left-drag on empty space orbits, Shift+left-drag box-selects, and drags starting on sketch geometry edit it; `hold` keeps the button down that many frames first (a right press-and-hold opens the marking menu, releasing over a direction picks it), `hold_end` that many frames at the end (a sketch drag shows its snap) |
|
||||
@@ -139,7 +139,7 @@ labels; `prefs:measure_axis_distances` identifies the checkbox.
|
||||
| `ui.sketchToScreen` | `points`: `[[x, y]…]` in active-sketch coordinates | their screen points (null when behind the camera) |
|
||||
| `ui.dialogInput` | `index` | what clicking an input's Select chip does: picks go to that input |
|
||||
| `ui.at` | `world: [x,y,z]` \| `sketch: [x,y]` \| `plane: "XY"` \| `axis: "Z"` \| `dimension: "d1"` (its value text) \| `handle: "arrow"` (a manipulator handle, see `scenario::publish_handle`) | the screen point (a scenario step's target; see `crates/ui-egui/src/scenario.rs`) |
|
||||
| `ui.handles` | `prefix?` | the handles drawn last frame, `[{name, x, y}]`: toolbar buttons and drop-down items `toolbar:<command id>` (the button alone: `button:<command id>`; a drop-down row: `dropdown:<command id>`, highlighted `dropdown_hot:<command id>`, its pin `dropdown_pin:<command id>`; Customize Toolbar's check boxes `customize:<command id>`), panel labels `panel:<tab>:<panel>`, browser rows `row:<label>` and fold arrows `fold:<label>`, manipulator handles; signed-axis tips `axis_view:z`, `axis_view:-y`; optional cube facets `navigation_cube:top`, `navigation_cube:top_front_right`, controls `navigation_cube:control:home` (and other actions), plus signed-axis aliases for visible cube faces; Preferences navigator picker `prefs:navigator`, options `prefs:navigator:Signed axes` and `prefs:navigator:Cube` |
|
||||
| `ui.handles` | `prefix?` | the handles drawn last frame, `[{name, x, y}]`: toolbar buttons and drop-down items `toolbar:<command id>` (the button alone: `button:<command id>`; a drop-down row: `dropdown:<command id>`, highlighted `dropdown_hot:<command id>`, its pin `dropdown_pin:<command id>`; Customize Toolbar's check boxes `customize:<command id>`), panel labels `panel:<tab>:<panel>`, browser rows `row:<label>` and fold arrows `fold:<label>`, manipulator handles; signed-axis tips `axis_view:z`, `axis_view:-y`; optional cube facets `navigation_cube:top`, `navigation_cube:top_front_right`, controls `navigation_cube:control:home` (and other actions), plus signed-axis aliases for visible cube faces; Preferences navigator picker `prefs:navigator`, options `prefs:navigator:Signed axes` and `prefs:navigator:Cube`; in the Motion Study dialog, where the chart puts its first and last step `motion:chart_start` and `motion:chart_end`, the Check collisions button `motion:check` and each collision found `motion:collision:<n>` |
|
||||
| `ui.editFeature` | `feature` (id or name) | what double-clicking a timeline item does: rolls back to it and opens its dialog filled in (sketches open in sketch mode) |
|
||||
| `ui.scroll` | `x`, `y`, `delta?` | wheel zoom at the cursor |
|
||||
| `ui.key` | `key` (egui key name, `Enter`, `Escape`…), `cmd?`, `shift?` | |
|
||||
|
||||
Reference in new issue
Block a user