mirror of
https://github.com/bherbruck/solidcraft.git
synced 2026-11-06 20:02:16 +00:00
27d2fe6ec0
* claim: #4003 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Frames: the profile library (#4003) The first slice of frames and weldments: the cross-sections structural members will be made of, each SolidCraft's own parametric definition built in code (no vendor or standard size tables are shipped). - solidcraft_doc::frame: bar, round bar, rectangular and round tube, angle, channel, I-beam and a generic T-slot extrusion as exact line/arc regions, with defaults worked out from the profile's size, refusals that name the dimension that does not fit, anchors and placement, and exact section properties (area, centroid, Ixx/Iyy/Ixy by Green's theorem). - frame.profile.list, frame.profile.properties (with mass per metre for a density) and frame.profile.insert (draws a profile into a sketch, locked by default, at a point, anchor and angle). - Tests against hand-computed values (rectangles, circles, composite rectangles by the parallel-axis theorem, fillet spandrels), hostile input, extrusion volume, undo; catalog entries in every locale; docs/frames.md; ROADMAP M15. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Frames: drop the built-in T-slot profile (#4003) Aluminium extrusions and other vendor sections come from the user's own sketch (drawn or inserted from the vendor's DXF), so the library keeps the plain steel shapes only. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Frames: members along frame sketch lines (#4003) frame.member lays one body per straight line of a frame sketch (2D lines or 3D sketch lines), its cross-section square to the line from end to end: - profile: a built-in profile, or profile_sketch, a sketch whose material (nested loops alternating, so two circles make a tube) is the section in its own x and y around its origin; profiles picks override it. - anchor (origin, centre, centroid or a bounding-box corner or edge middle), angle (an angle expression, so a parameter), mirror. - Orientation: the profile's y as near world up as the line allows, x square to both; a vertical member's x is world X (frame::member_axes). - Members follow sketch and parameter edits, undo as one step, save and reopen (format: pending/frame-members.rs), and are named after the profile (Rect Tube 40x40x3, (2)…), numbering on past names already taken. Tests against hand-computed volumes and bounding boxes (rectangle, 3D tower lines, parameter edit, sketch tube profile and picks, anchor/angle/ mirror), refusals, undo/redo and reopen; walk fixtures and goldens; docs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Frames: fixes from the adversarial review (#4003) - Default member lines are what was drawn: projected and other linked curves and 3D wires (a face sketch's edges) and lines of no length are left out. - A profile sketch's material starts from its drawn profiles, as solid.extrude's "all" does, so a section sketched on a face works; the even-odd test uses outlines and boxes worked out once, capped at 256. - Member names are pinned to their lines (`names`, by line id; `body_name` is the base): deleting or adding a line, or deleting another feature, no longer renames other members, and frame.member stores every name it gives. body.rename renames a member on its line (also for later member features); a copy whose body_names were set still names its members by position. - Built-in profile dimensions are expressions (ProfileSpec): they follow parameters, bare numbers take the design's units, and they are feature inputs. frame.profile.properties/insert read them the same way. - Default root/toe radii shrink to the room a thick section leaves; radii given are checked by name; a radius must be 0 or at least 0.01 mm; error messages report the wall or flange value given, not twice it. - A line within 1e-6 rad of vertical orients as vertical, so rounding never turns a post a quarter turn. - A 2D frame sketch in a differently placed component is mapped into the member's frame, and member features recompute when placements change. - Caps before lookups for a design's `lines`; a line listed twice is refused; a 3D wire that runs back on itself is not a line. Regression tests for each, from the review's scenarios. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Frames: the Frame Member dialog on the ribbon (#4003) - Frame Member (MODEL > Create) opens a dialog: the frame sketch's lines picked in the view (or All Lines), a built-in profile and its dimensions or a section picked in another sketch, anchor, angle, mirror and name, with a live preview. Edit Feature reopens it filled in. - Lines picked in the view keep their sketch (a SKETCH_LINES input picks ExternalSketchCurve): line ids are each sketch's own, so two 3D sketches both have a `w2`, and the members went on the newer sketch's lines. - timeline.redefine takes frame.member. Members keep their names through an edit unless it gives them a new body_name; frame.member takes `names`. - A member whose section is a whole profile sketch keeps it when edited (the dialog shows the sketch instead of picking every region, which would fill a tube's hole). - An original frame_member icon, open for review, on the ribbon, timeline and browser. - The angle profile is listed as L-Angle, and web and flange as Web/Flange thickness, so they translate apart from the existing Angle, Web and Flange; the dialog's labels are in en, ja and zh. en-GB no longer repeats the frame command labels it spells the same. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
113 lines
7.3 KiB
Markdown
113 lines
7.3 KiB
Markdown
# Frames and weldments
|
||
|
||
Frames and weldments (#4003) are structural members (tube, angle, channel, beam, an aluminium
|
||
extrusion of your own) laid along the lines of a frame sketch. This page covers what has landed:
|
||
members and their profiles. Corners, trims, end caps, gussets, welds and the cut list follow.
|
||
|
||
## The workflow
|
||
|
||
1. **Sketch the frame**: lines in a sketch, or a 3D sketch for a frame that leaves one plane
|
||
(`sketch.options sketch_3d: true`, then `sketch.line3d`). Drive the sizes with parameters as
|
||
usual; members follow.
|
||
2. **Choose a profile**: a built-in one from its dimensions (below), or your own drawn in a sketch
|
||
(a vendor's extrusion: insert their DXF with `sketch.insert_dxf`). A profile sketch's origin is
|
||
the point that sits on each line, and its x and y are the profile's.
|
||
3. **Add members**: **Frame Member** (MODEL › CREATE, `frame.member`) makes one body per line,
|
||
square to it, from its start to its end. Repeat with another profile for the next group of
|
||
lines.
|
||
|
||
```json
|
||
{"command": "frame.member", "params": {"sketch": "Frame", "profile": {"kind": "rect_tube", "width": 40, "height": 40, "wall": 3}}}
|
||
{"command": "frame.member", "params": {"sketch": "Frame", "lines": ["l5", "l6"], "profile_sketch": "45x45 section", "anchor": "bottom_left", "angle": "90 deg"}}
|
||
```
|
||
|
||
Members are ordinary bodies: mirror, pattern, move, drill and combine them with the usual
|
||
commands. Where members meet they overlap until corner treatments land.
|
||
|
||
## The Frame Member dialog
|
||
|
||
- **Lines**: pick the frame sketch's lines in the view (2D or 3D sketch lines). **All Lines**
|
||
makes a member on every line of that sketch instead, including lines drawn later.
|
||
- **Section (optional)**: pick the section's region in another sketch (the ring between two
|
||
circles makes a tube). With nothing picked, **Profile** chooses a built-in profile and its
|
||
dimensions follow; optional ones left empty take their defaults.
|
||
- **Anchor**, **Angle** and **Mirror** place the section on each line, as below. **Name** names
|
||
the members (default: after the profile).
|
||
- The preview shows the members as you change the values. **Edit Feature** reopens the dialog with
|
||
the feature's values; the members keep their names through the edit, and a new **Name**
|
||
renames them all. A member made with a whole profile sketch keeps it (the **Section** row shows
|
||
the sketch; untick it for a built-in profile).
|
||
|
||
## frame.member
|
||
|
||
- `sketch`: the frame sketch. `lines`: the curve ids to lay members on (2D lines or 3D sketch
|
||
lines), each once; left out, every straight line drawn in the sketch: not construction, not
|
||
projected or otherwise linked (a sketch on a face projects the face's edges; they are
|
||
references, not members), and with a length.
|
||
- `profile` (a built-in profile) or `profile_sketch` (a sketch), one of them. A profile sketch's
|
||
section is its material as nested loops alternate (an outline is material, a loop inside it a
|
||
hole, a loop inside that material again), so two circles make a tube; pick other regions with
|
||
`profiles` as `solid.extrude` takes them. Like `solid.extrude`, only what was drawn counts:
|
||
projected edges are left out unless the drawn curves make no profile. It must be one piece.
|
||
- `anchor`: the profile point on the line: `origin` (the default: a built-in profile's centre, a
|
||
profile sketch's origin), `center` (of its bounding box), `centroid`, or a corner or edge middle
|
||
of its bounding box (`bottom_left`, `top`…).
|
||
- **Orientation**: the profile's y points up (world +Z) as far as the line allows and its x is
|
||
square to the line and to y (x × y runs along the line, so on a line along +X the profile's x is
|
||
world +Y); a vertical member's x is world +X. `angle` (an angle expression) turns the profile
|
||
about the line, counter-clockwise looking back from the line's end; `mirror` mirrors it across
|
||
its y axis first. A line leaning less than 10⁻⁶ rad from vertical counts as vertical, so
|
||
rounding in a 3D sketch never turns a post a quarter turn.
|
||
- Bodies are named after `body_name`, or the profile (`Rect Tube 40x40x3`) or the profile
|
||
sketch, then numbered on past names already taken (`(2)`, `(3)`…). Each member's name is kept
|
||
with its line (the feature's `names`), so deleting or adding a line, or deleting another
|
||
feature, leaves the other members' names alone; `body.rename` renames a member on its line.
|
||
`names` (`{line id: name}`) gives names to keep, as Edit Feature (`timeline.redefine`) passes
|
||
them unless the edit changes `body_name`.
|
||
|
||
Every built-in profile is SolidCraft's own parametric definition, built in code
|
||
(`solidcraft_doc::frame`). SolidCraft ships no vendor's or standard's size table: you give the
|
||
dimensions of the stock you buy. Any other section, a vendor's aluminium extrusion for example, comes
|
||
from a sketch: draw it or insert the vendor's DXF.
|
||
|
||
## Built-in profiles
|
||
|
||
A profile is JSON with a `kind` and its dimensions, each a number in the design's units or a
|
||
length expression over its parameters (`"tube_wall"`, `"2 in"`): a member follows a parameter
|
||
change like any feature. Dimensions marked *optional* default from the profile's size when left
|
||
out, made smaller where a thick section leaves less room for a radius;
|
||
`frame.profile.properties` returns the profile in millimetres with every default written out.
|
||
|
||
| Kind | Required | Optional (default) |
|
||
|---|---|---|
|
||
| `bar` | `width`, `height` | `corner_radius` (0) |
|
||
| `round_bar` | `diameter` | |
|
||
| `rect_tube` | `width`, `height`, `wall` | `outer_radius` (2 × wall; inner radius is outer − wall) |
|
||
| `round_tube` | `diameter`, `wall` | |
|
||
| `angle` | `width` (leg along x), `height` (leg along y), `thickness` | `root_radius` (thickness), `toe_radius` (thickness / 2); together at most the shorter leg's inside length |
|
||
| `channel` | `height`, `width` (flange length), `web`, `flange` (thicknesses) | `root_radius` (web, at most the room in a flange and half the web's inside height), `toe_radius` (0) |
|
||
| `i_beam` | `height`, `width`, `web`, `flange` | `root_radius` (web, at most the room in a flange and half the web's inside height) |
|
||
|
||
The profile's bounding box is centred on its origin, x across and y up. Angles have their heel at
|
||
the bottom left; channels open towards +x.
|
||
|
||
Dimensions are refused, with the dimension named, when they are not finite, are outside
|
||
0.01 mm–10 m (radii: 0, or 0.01 mm–10 m), or do not fit: a wall of half the tube or more, a radius
|
||
given larger than the room for it.
|
||
|
||
## Commands
|
||
|
||
- `frame.profile.list`: every kind, its dimensions and a working example.
|
||
- `frame.profile.properties` `{profile, density?}`: the section, worked out exactly from its lines
|
||
and arcs: `area` (mm²), `centroid` (mm from the bounding box centre), `ixx`, `iyy`, `ixy` (mm⁴
|
||
about the centroid), `width`, `height`; with `density` (kg/m³), `mass_per_m` (kg/m).
|
||
- `frame.profile.insert` `{profile, at?, anchor?, angle?, fixed?, sketch?}`: draws the profile into
|
||
the sketch being edited, its `anchor` point (`center`, `centroid`, or a corner or edge middle of
|
||
the bounding box such as `bottom_left`) on `at`, turned by `angle` radians. The curves are locked
|
||
(`fixed`, default true) so solving the sketch keeps the shape. The outline and each hole are
|
||
separate sketch regions: extrude the material region (pick it with `profiles: [{point}]`).
|
||
|
||
```json
|
||
{"command": "frame.profile.insert", "params": {"profile": {"kind": "rect_tube", "width": 40, "height": 40, "wall": 3}, "at": [0, 0], "anchor": "bottom_left"}}
|
||
```
|