A linear or aligned dimension whose normal is not world Z was drawn and
exploded as if it lay in world XY. The builders read the offset and the
extension directions in XY only, so a dimension turned into a working plane
such as XZ lost its offset (now along Z): the dimension line fell onto the
measured points and the extension lines stuck out along world Y.
Move such a dimension into its own OCS before building it and map the result
back onto its plane, as arc length and large radial dimensions already do,
for both tessellation and EXPLODE.
Co-Authored-By: Claude Opus 5 <[email protected]>
Optimize wide and tapered arc fill mesh generation by eliminating general
ear-clipping triangulation and optimizing arc boundary evaluation:
1. Replaced triangulate_planar with triangulate_band_ring and direct
quad-strip vertex construction in wide_band_tris. Polyline band fills
possess strict quad-strip topology (straight segments: 4-vertex trapezoid;
arc segments: 2m-vertex annular sector). Generating triangles directly in
O(N) time avoids Newell normal calculation, planar projection, Delaunay
triangulation, and O(N^2) ear-clipping searches.
2. Exact buffer capacity pre-allocation in wide_band_tris based on ring
lengths, eliminating dynamic reallocation during triangle emission.
3. Replaced top and bottom cap triangulation in thick_band_tube with
triangulate_band_ring.
4. Unified inner and outer arc point calculation in polyline_segment_fill
into a single loop using ang.sin_cos(), halving trigonometric calls and
eliminating dynamic vector resizing.
Performance gains (wide_and_tapered_arc_tessellation benchmark across 7,500 entities):
- Latency: 27.34 ms -> 23.30 ms (-14.8%)
- Mean latency: 28.08 ms -> 24.15 ms (-14.0%)
- Throughput: 265.6k entities/s -> 321.9k entities/s (+21.2%)
- Correctness: 100% pass across all 45 polyline and 5 tessellation unit tests.
With a working plane other than world XY, ROTATE and MIRROR handed a
non-ordinate dimension to acadrust's Entity::apply_transform, which only
translates those dimension types by where the transform sends the origin.
The definition points, plane and angles stayed unturned, so the dimension
jumped back once its block was baked again.
Send both through the existing Affine branch, which ALIGN already uses and
which transforms points, normal and stored angles together. The world-Z
paths are unchanged.
Co-Authored-By: Claude Opus 5 <[email protected]>
Rotating geometry leaves float noise in coordinates: turning the point
(0, 10) by 180 degrees gives X = -1.2246e-15. Rust formats that as
"-0.0000", so Properties showed "-0.0000" (or -0", -0d0'0", -0g) for a
value that is zero at the drawing's precision.
format_length and format_angle now drop the sign when every printed digit
is zero. Values that still show a digit keep it, and scientific notation
is unaffected.
Co-Authored-By: Claude Opus 5 <[email protected]>
ROTATE and MIRROR in the drawing plane moved a linear dimension's points
but left its stored rotation (the axis it measures along) unchanged. A
horizontal dimension rotated 90 degrees then measured its now-vertical
points along X and its value dropped to 0; mirroring about a slanted line
did the same. Polar ARRAY goes through the same path.
Turn the axis by the rotation angle, and reflect it about the mirror line.
A zero-length mirror line still leaves the dimension untouched.
Co-Authored-By: Claude Opus 5 <[email protected]>
DIMTMOVE=1 ("moves the text and adds a leader") draws the leader from the midpoint
of the dimension line to the text, so a text dragged outside the dimension line gets
a diagonal that starts in the middle of the line and crosses the extension lines.
Mechanical-drawing practice (GB/T 4458.4, and what AutoCAD itself draws) extends the
dimension line along its own axis so that it runs underneath the text. Linear and
aligned dimensions now do that whenever the text is outside the dimension-line extent;
when the text is still inside it (only moved up/down) the previous connect-to-text
leader is kept. Every other dimension type is unchanged, and only dimensions with
DIMTMOVE=1 are affected at all (the shipped default is 0).
Adds four unit tests covering the placements (outside right, outside left, inside,
radius draws none) plus an integration render smoke test driven through the real
Scene::entity_wires() -> export_pdf() pipeline, gated by OCS_DIM_LEADER_PDF so CI
stays side-effect free.
- Emit shaped fill triangles and outline strokes instead of unshaped SDF quads
- Update bounding box to include fill triangles
- Add unit test for multileader arabic text tessellation
- Enable fallback font metrics for HarfBuzz shaping in TTF glyph resolver
- Implement Unicode Bidirectional Algorithm (UBA) paragraph base direction detection
- Anchor right-to-left paragraphs to right container boundaries by default
- Reorder line atoms with base direction level to preserve neutral punctuation attachment
- Right-align RTL single-line TEXT and handle editor caret placement on RTL glyphs