Picks 2+ profile entities (closed or open wires), builds ruled shells
between consecutive pairs via builder::try_wire_homotopy, caps closed
ends with planar faces, and tessellates the result into a Solid3D mesh.
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
Picks a profile (closed or open 2D entity) then a path entity
(Line or LwPolyline). For Line paths uses tsweep along the line
vector; for Polyline paths uses start→end as translation direction.
Closed profiles produce a capped Solid; open profiles a Shell.
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
BOX, SPHERE, and CYLINDER build truck topology solids and tessellate
them into MeshModels stored alongside a Solid3D placeholder entity so
the GPU mesh pipeline renders them immediately.
EXTRUDE picks any closed 2D profile (Circle, LwPolyline, etc.),
attaches a planar face via try_attach_plane, and translational-sweeps
it (tsweep Face → Solid) along Z by the given height.
REVOLVE picks a profile, two axis points, and an angle (default 360°),
then rotational-sweeps the wire (rsweep) around the axis.
Three new CmdResult variants drive the operations:
CommitSolid3D, ExtrudeEntity, RevolveEntity.
Scene::layer_color() added to retrieve the active layer's RGBA color.
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
REFEDIT picks an INSERT, extracts the block entities into model space
with the INSERT transform applied (translate + rotate + uniform scale),
and enters an editing session. Any normal modify command works on the
temporary entities.
REFCLOSE SAVE applies the inverse transform, replaces the block
definition, and rebuilds all derived caches (hatch/image/mesh), so
every INSERT of that block reflects the edits immediately.
REFCLOSE DISCARD removes the temp entities without changing the block.
Non-uniform-scale inserts are rejected with an error message.
RefEditSession is stored on DocumentTab; undo snapshots bracket the
begin and close operations.
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
Three-dimensional rectangular array: prompts for rows, columns, levels
and their respective spacings, then generates copies translated along
X (columns), Z (rows in drawing plane), and Y (levels / height).
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
When inserting a block that contains AttributeDefinition entities,
the INSERT command now enters an attribute-filling phase: each attdef
is prompted tag-by-tag (showing its prompt text and default value).
Pressing Enter accepts the default. The completed AttributeEntity list
is embedded in the Insert before committing.
Blocks without attdefs continue to insert immediately as before.
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
- ordinate_dim.rs: OrdinateDimCommand picks feature point then leader
endpoint; auto-detects X vs Y ordinate from movement direction
- Ordinate dim added to the Dimensions dropdown in the Annotate ribbon
- ROADMAP.md: DIMORDINATE ✅, Named UCS (already implemented) ✅
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
- attedit.rs: AtteditCommand picks an INSERT entity then iterates through
each attribute tag prompting for a new value (Enter keeps existing)
- attedit_pending_handle() / attedit_set_attrs() trait methods inject
attribute data into the command after entity-pick (avoids document access
in the command itself)
- cmd_result.rs: NeedPoint handler injects attr data; ReplaceEntity detects
the __ATTEDIT__ sentinel and calls apply_attedit() on the document
- apply_attedit() encodes tag/value pairs as __ATTEDIT__tag\x01val\x02...
- ROADMAP.md: ATTEDIT marked ✅
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
- splinedit.rs: SplineditCommand picks a spline (entity-pick phase) then
accepts CLOSE/OPEN/REVERSE/EXIT sub-commands via text input
- apply_spline_op() mutates the spline in the document directly, with knot
vector regeneration via generate_clamped_knots()
- Sentinel XLine trick: ReplaceEntity with a magic __SPLINEDIT_* layer name
is intercepted in cmd_result.rs before erasing the original entity
- Control-point dragging already works via the existing grip editing system
- ROADMAP.md: SPLINEDIT marked ✅
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
- src/modules/insert/wblock.rs: extract_block_to_doc() copies a named
block's entities into a fresh CadDocument; extract_entities_to_doc()
does the same for a selection set; layer definitions are carried over
- WBLOCK <name> writes the named block; WBLOCK * writes selected entities
- WblockSave / WblockSaveResult messages drive the async save-dialog flow
- ROADMAP.md: 1.10 WBLOCK marked ✅
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
Both commands detect which terminal segment/vertex is nearest to the
pick point, compute the new endpoint along the segment direction, and
move only that terminal vertex — preserving all other vertices and bulge
values intact. ROADMAP updated: EXTEND and LENGTHEN marked ✅.
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
Add shared spline_ops module with:
- spline_to_bspline / bspline_to_spline: acadrust ↔ truck BSplineCurve conversion
- spline_sample_xy: sample DXF-XY projection at N+1 points with parameters
- spline_nearest_t: nearest-parameter search via coarse+bisection
- spline_pts_wire: world-space wire points for WireModel preview
TRIM: Spline entities can now be used as cutting boundaries (Geo::Spline
sampled into polyline segments) and as entities being trimmed; uses
BSplineCurve::cut() to produce surviving pieces.
EXTEND: extend_spline() shoots a tangent ray from the nearest endpoint
and appends a control point at the first boundary hit.
OFFSET: offset_spline() offsets each sample point along the local
perpendicular normal and rebuilds a new spline from the offset control pts.
BREAK: break_spline() uses spline_nearest_t() + BSplineCurve::cut() to
split the spline at one or two click points.
LENGTHEN: lengthen_spline() uses numerical arc-length integration +
bisection to cut the spline at the parameter corresponding to the new
requested length.
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
Decomposes Dimension (Linear, Aligned, Radius, Diameter, Angular2Ln,
Angular3Pt, Ordinate) into constituent Lines (extension lines, dimension
line) plus a Text entity for the dimension label value.
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
Replaced the simplified MOVE-based STRETCH with a real crossing-window
implementation. Workflow: pick two crossing-window corners, then base+target
points. Only vertices/endpoints inside the window are translated:
- Line: moves start/end independently
- LwPolyline/Polyline: moves individual vertices inside window
- Arc/Circle/Ellipse: moves whole entity if center is inside
- Insert/Text/MText: moves if insertion point is inside
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
Add HATCHEDIT (HE alias) command. Works on pre-selected hatch or via
entity pick. Accepts text options: P <pattern>, S <scale>, A <angle>.
Enter applies changes; rebuilds hatch entity and GPU model via add_hatch.
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
Add DDEDIT (ED alias) command that edits Text/MText/Attribute entities
in-place via the command line. Double-clicking a text entity in model space
now auto-launches DDEDIT for that entity. Supports Text, MText,
AttributeDefinition, and AttributeEntity types.
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
Extended FilletCommand and ChamferCommand to accept Lines and Arcs as
first/second entity. Added fillet_line_arc() and fillet_arc_arc()
geometry functions that find a tangent fillet circle between the two
entities, trim each to the tangent point, and insert the fillet arc.
r=0 case trims/extends to the nearest intersection without inserting an arc.
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
- Add explode_mline() that decomposes each MLine segment into its
spine Line plus two ±scale/2 offset Lines using per-vertex miter
directions, matching the visual representation of MLine entities
- Update file header to document all actually-supported entity types
(LwPolyline, Polyline2D/3D, Polyline, Insert, MLine)
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
Add lengthen_ellipse() that approximates the arc length via 128-point
numerical integration, then bisects to find the new angular span matching
the requested delta/total/percent, and adjusts the nearer endpoint.
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
Add offset_ellipse() that scales both semi-axes uniformly by the offset
distance (inside vs outside determined by projecting side_pt onto the
ellipse local frame). This is the standard CAD approximation; a true
offset of an ellipse is a higher-order Lamé curve.
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
Add break_ellipse() that projects the two break points onto the ellipse
parameter space (eccentric anomaly) and removes the CCW segment between
them, producing a partial Ellipse entity — matching AutoCAD break behaviour.
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
- Add Ellipse variant to the Geo boundary enum
- Implement algebraic line-ellipse intersection (le()) for fast boundary checks
- Add ellipse_seg_ts() using bisection for all boundary types including
Arc/Circle/Ellipse boundaries (64-sample sign-change + 32-step bisection)
- Add trim_ellipse() producing partial Ellipse entities with updated parameters
- Add extend_ellipse() to stretch an ellipse arc to the nearest boundary
- Wire Ellipse into TrimCommand and ExtendCommand: on_entity_pick,
on_entity_replaced, and on_hover_entity (live red/cyan preview)
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
- MLSTYLE command: LIST, NEW, SET, DEL subcommands
- Multiline Style Manager dialog: style list, element details (offset,
color, linetype), Set Current / New / Delete buttons
- MLINE/ML command now reads document header.multiline_style to apply
the current style to newly created MLine entities
- MlineCommand.with_style() constructor for style-aware multiline drawing
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
DIMALIGNED: 3-click flow (p1 → p2 → dim line position) → DimensionAligned.
Rubber-band preview shows extension lines and dim line offset.
DIMDIAMETER: 3-click flow (center → arc point → text position) → DimensionDiameter.
Previews the diameter chord line.
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
Entity pick → text input subcommands:
C / CLOSE → set closed flag
O / OPEN → clear closed flag
W <value> → set uniform width on LwPolyline vertices
X / EXIT → cancel
Command stays active after each op (CmdResult::PeditOp) for multiple edits.
Supports LwPolyline and Polyline2D.
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
Pick vertices, Enter to finish (≥2 pts). Text input while picking:
C / CLOSE → close and commit (≥3 pts)
S <value> → set scale factor (default 1.0)
S alone → prompt for scale then continue
Uses acadrust MLine::from_points / closed_from_points + scale_factor field.
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
Pick polygon corners, Enter to close. Each edge is subdivided into arc
bumps (bulge = 0.5 ≈ 53° arcs). Result is a closed LwPolyline.
Arc bump length defaults to 1.0 drawing units.
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
Options via text input after entity pick:
DE <delta> — extend by delta (negative trims)
TO <total> — set absolute total length / arc length
P <percent> — scale by percentage
<number> — plain number treated as DE delta
Closest end to pick point is modified. Uses CmdResult::LengthenEntity.
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
Selection-gathering mode: select objects, press Enter to apply.
- Lines: checks collinearity + no-gap, merges into single line span
- Arcs: checks same center/radius + contiguous angles, merges to Arc or Circle
- Uses CmdResult::JoinEntities; geometry computed in cmd_result from document
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
3-step interactive flow:
1. Entity pick (first break point recorded at click location)
2. Optional first point refinement
3. Second break point → CmdResult::BreakEntity applied in cmd_result
Geometry:
- Line: project p1/p2 onto line parameter space → two line fragments
- Arc: project p1/p2 to arc angles → trim CCW from p1 to p2
- Circle: same as Arc, converts Circle → Arc
- LwPolyline: nearest-vertex split → two polyline fragments
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
Add three classic CAD measurement commands:
- DIST (DI): two-point pick → distance, angle, delta XYZ
- ID: one-point pick → coordinates
- AREA: multi-point polygon pick (Enter to close) → area + perimeter
New CmdResult::Measurement(String) variant ends active command and
prints result to command line without modifying the document.
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
- Enforce status.locked in pan_active_viewport and zoom_active_viewport:
locked viewports now reject pan/zoom inputs entirely
- Add perspective, render_mode, shade_plot_mode, hide_plot, ucs_icon_visible
fields to the viewport property panel with appropriate pickers/toggles
- Add VPORTS command: lists all user viewports in the current layout
(id, size, position, scale, on/locked state) in the command line
- Add VPLAYER command: per-viewport layer freeze/thaw from the command line
(F <layer> to freeze, T <layer> to thaw, Enter to exit)
- Add CmdResult::VpLayerUpdate variant and its handler in apply_cmd_result
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
The preview rectangle used c1.y (constant) for all four corners and
pt.z for Z instead of c1.z. Corners 3 and 4 now correctly use pt.y
(varying Y) and the constant c1.z, producing a proper XY-plane rectangle.
Fixed in both layout/mview.rs and manage/mview.rs.
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
- Add printpdf 0.9.1 dependency for native PDF generation.
- New src/io/pdf_export.rs: converts paper-space WireModels to a PDF
page (per-wire stroke color, line weight in Pt, NaN-split segments).
White/near-white colors are inverted to black for print output.
- Add PlotExport / PlotExportPath messages: opens a save-file dialog
and writes a .pdf next to the drawing file.
- Add PageSetupOpen/Close/WidthEdit/HeightEdit/Commit messages: a
centered modal panel lets the user enter paper width and height (mm);
on commit the Layout object's min/max_limits are updated in-place.
- Register PRINT / PLOT / EXPORT and PAGESETUP (PS) commands in
dispatch_command; fix MVIEW error message to English.
- Layout ribbon gains a "Plot" group with Page Setup and Export PDF
ribbon buttons.
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
- Deactivate ribbon tool highlight when command ends (issue #1)
- Reset last_point on new command dispatch to fix polar snap offset (issue #2)
- FILLET/CHAMFER: disable text input during entity pick so clicks reach viewport (issue #3)
- Dropdown icon buttons now use RibbonToolClick so they highlight blue when active
- FILLET/CHAMFER: AutoCAD-style sub-step UX — typing R/D + Enter prompts for value
- Fix FILLET arc preview plane: arc was rendering in XZ instead of XY
- Bump version to 0.1.1
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
Each command implementation is now in the same file as its ribbon
tool definition. Groups moved to a dedicated groups/ toolbar folder.
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>