The offset core moves out: normalising the source, the cavalier_contours
call, the sharp-corner join fixup and the conversion back. What stays is
entity work — reading an LwPolyline in, writing offset LwPolylines out,
and the per-type offsets for lines, arcs, circles, ellipses and splines,
which are analytic and never needed the polyline machinery.
`BulgeArc` moves with it, since the offset preprocessing splits over-half-
turn arcs and cannot work without it. `entities::common` now re-exports it
from the kernel, so the twelve modules already reaching for
`entities::common::BulgeArc` are untouched.
`norm_rad` was a fourth copy of angle normalisation, after the three
removed from trim, fillet and explode. It now aliases the kernel's.
cavalier_contours leaves this crate's manifest: nothing here calls it any
more, and it arrives through the kernel's `offset` feature instead, which
acadifc forwards.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Two faults met on the same command, both of them older than the move to
cadkernel and both hidden until ellipse previews started rendering
truthfully.
The survivor came back in two pieces. `trim_ellipse` handed its cuts to
`trim_intervals`, which is the open-curve routine: it anchors on bounds at
0.0 and 1.0, so a closed ellipse gained invented cuts at the parameter
seam and the surviving arc arrived split either side of it. Worse, a click
in the wrapping piece landed in one of those two halves, so the wrong span
disappeared. A closed ellipse now takes the cyclic route circles already
used — find the cut-to-cut gap holding the click, keep everything else,
and let end < start signal the wrap.
The cut span was also short. That came from `line_ellipse`, fixed upstream
in cadkernel 46e76cc: it returned the geometric angle at the centre rather
than the ellipse parameter, which are the same thing only on a circle. On
anything eccentric the cuts sat tens of degrees off where the line
actually crossed, so the removed piece was consistently too small. The
lock bump brings that fix in.
Elliptical arcs, lines, rays, xlines and open splines keep using
`trim_intervals`; nothing about the open-curve path changes.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
TRIM, FILLET and EXPLODE each carried their own copy of the same plane
maths. The copies had already drifted apart: `ll` differed only in
parameter names between trim.rs and fillet.rs, `arc_pts` only in which
angle helper it called, and `norm` meant angle normalisation in trim.rs
and explode.rs while meaning vector normalisation in two other files.
The implementations now live in cadkernel's geom2d. A new local `geom`
module adapts the call shapes — the kernel takes `[f64; 2]` points and
returns `[f64; 3]`, while these commands pass loose scalars and feed
`WireModel::points`, which is `[f32; 3]`. Narrowing stays on this side
because only the caller knows whether it is a preview wire, which leaves
`points_low` empty and accepts the loss, or resident geometry, which
splits the f64 into a high/low pair instead.
Call sites are untouched: the kernel functions are imported under the old
local names, so the signatures they were written against still hold.
This also fixes ELLIPSE trim and extend previews. `ellipse_pts` wrote its
components as [x, z, y] while `arc_pts` — reached from the same match in
`entity_pts`, feeding the same `[f32; 3]` — wrote [x, y, z], and
`WireModel::points` is documented as world-space positions. Ellipse
previews were collapsing onto y = 0 and displacing along Z. The kernel's
`ellipse_arc` orders them correctly, so delegating corrects it.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The DWG/DXF/ACIS codec now lives in its own crate and acadifc re-exports
it alongside the geometry kernel, so this is the single dependency:
OpenCADStudio -> acadifc -> { cadcodec, cadkernel }
acadifc is aliased to `acadrust`, which leaves the 2569 `use acadrust::…`
paths across 253 files untouched — the alias is a manifest-level rename,
not a source change.
The old `[patch.crates-io]` entry goes away with it: the dependency is a
git revision now rather than a crates.io version being redirected.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Two places still showed the old mark after the logo was redrawn.
The window icon was built by drawing the letterforms stroke by stroke in
code, background colour and all, which made it the one icon in the
application not coming from assets/logo.svg. It now rasterises that file,
fitted to the square without distorting whatever aspect the logo has. It
returns nothing when the logo cannot be rendered, so the window falls back
to the platform default instead of to something invented here -- which is
how it ended up stale in the first place.
The icon installed into the icon theme was only ever written from inside
the desktop-entry write, behind that write's own "nothing changed" early
return. The entry's text does not change when the logo does, so once it
had been written the icon was never refreshed again. The two change for
different reasons; the icon is now checked first and on its own terms. It
already compares bytes, so an unchanged logo still costs only a read.
Worth knowing on Wayland: the compositor ignores the window icon entirely
and takes the dock icon from the desktop entry, so there the installed
theme file is the only one that matters -- and it refreshes when the file
associations are next set up, not at launch.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The merged fix added the rotation update on this side, matching only
`EntityTransform::Rotate`. That left `Affine` -- which several entity
paths and the UCS world transform emit -- still dropping the angle, and
it sat against the contract this crate already relies on: MIRROR is
delegated precisely because acadrust's entity-aware paths "handle
direction flags, stored-angle conventions and bulges themselves", and
`mirror_text` did exactly that for the same field.
Moved upstream (acadrust 9ecaffc), where one helper carries the angle for
every entity that keeps one. That covers rotation, affine and reflection
in a single place, and closes the same gap for SHAPE and the ATTRIB pair,
which a rotation left facing the old way too -- attributes noticeably so,
since INSERT already turned itself while its attributes did not.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
A drawing whose bodies are built only of planes opened without error but
drew nothing, while the solids still selected. Pre-7.0 SAT writes strings
as a length and the characters, so one may contain the record
terminator; ODA's builder emits `8 STEP Id#` inside a dxid-attrib. The
parser split there, every later record answered to the wrong index, and
faces resolved their surface pointer to a coedge or a vertex, so nothing
meshed.
Fixed upstream in acadrust 41149d7. All 22 solids in the reported drawing
now parse to exactly the record count their header declares, and all 22
mesh.
Closes#670
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Scope revolution spans to face boundaries and preserve pierced cylinders and rational spline lofts so valid bodies no longer produce stretched or missing shells.
Pin Iced 0.15 so dialogs can measure content before distributing the resolved frame across child panels. Keep the web plugin notice compact and non-resizable.\n\nCloses #582
Use the operating system trust store and Windows proxy settings while keeping TLS verification enabled. Add retryable registry errors with copyable diagnostics.\n\nRefs #563
Keep storage fast paths on capable adapters and use packed or texture fallbacks only when device limits require them.\n\nCompact mesh-edge varyings to avoid WebGL shader rejection.
Replace full-document snapshots with Arc first-touch deltas and batch cache invalidation. Reuse interaction and GPU category caches across unrelated edits.
Solid hatches carrying stale GradientColor1/2ACI EED (no ACAD_XREC_ROUNDTRIP
XRecord) no longer resurrect as a two-colour gradient — red / ACI-253 solids
now render solid instead of blue→yellow.
Closes#471
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Heavy 2D POLYLINE vertices with absent width codes now inherit the
polyline default while explicit-zero segments stay zero, so tapered
polylines (e.g. sample_AC1009 handle 0x35B) render variable-width
instead of constant — matching the DWG/LWPOLYLINE form.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>