feat(ucs): orient text-bearing annotations to the active UCS
New annotations now place their text and reading geometry along the active UCS X axis (identity = world), so they read square to the user's coordinate system instead of world-horizontal: - TEXT / MTEXT: rotation defaults to the UCS X angle (DocumentTab::ucs_rotation_angle, model space only). - Linear dimensions: measure along the UCS axis the span is nearest, and bake the UCS X angle as the text rotation so the value reads square even under a style that forces horizontal text. DIMCONTINUE / DIMBASELINE derive their axis from the base dim's rotation (any angle), not a world H/V test. - LEADER: the MText annotation rotates to the UCS, and the hookline runs along the leader's horizontal_direction (set to UCS X), used by the renderer instead of world horizontal. - MLEADER: context.text_direction = UCS X drives both the text rotation and, in the renderer, the text side and dogleg/landing direction. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
0c2a97e17e
commit
33314a5889
10 changed files with 160 additions and 73 deletions
|
|
@ -65,7 +65,19 @@ fn to_truck(leader: &Leader) -> TruckEntity {
|
|||
if leader.hookline_enabled && verts.len() >= 2 {
|
||||
let last = verts.last().unwrap();
|
||||
let prev = &verts[verts.len() - 2];
|
||||
let sign = if (last.x - prev.x) >= 0.0 {
|
||||
// Landing runs along the leader's horizontal direction (UCS X for
|
||||
// UCS-placed leaders, world X otherwise), on the side the leader
|
||||
// approaches from.
|
||||
let (hx, hy) = {
|
||||
let h = leader.horizontal_direction;
|
||||
let l = (h.x * h.x + h.y * h.y).sqrt();
|
||||
if l > 1e-9 {
|
||||
(h.x / l, h.y / l)
|
||||
} else {
|
||||
(1.0, 0.0)
|
||||
}
|
||||
};
|
||||
let sign = if (last.x - prev.x) * hx + (last.y - prev.y) * hy >= 0.0 {
|
||||
1.0_f64
|
||||
} else {
|
||||
-1.0_f64
|
||||
|
|
@ -74,7 +86,11 @@ fn to_truck(leader: &Leader) -> TruckEntity {
|
|||
let last_f = p3(last);
|
||||
points.push(nan);
|
||||
points.push(last_f);
|
||||
points.push([last_f[0] + sign * len, last_f[1], last_f[2]]);
|
||||
points.push([
|
||||
last_f[0] + sign * len * hx,
|
||||
last_f[1] + sign * len * hy,
|
||||
last_f[2],
|
||||
]);
|
||||
}
|
||||
|
||||
TruckEntity {
|
||||
|
|
|
|||
|
|
@ -102,11 +102,22 @@ fn to_truck(ml: &MultiLeader, document: &acadrust::CadDocument) -> Option<TruckE
|
|||
.copied()
|
||||
.or_else(|| ml.context.leader_roots.first().map(|r| r.connection_point))
|
||||
.unwrap_or(text_loc);
|
||||
let text_sign: f64 = if text_loc.x >= leader_ref.x {
|
||||
1.0
|
||||
} else {
|
||||
-1.0
|
||||
// Reading direction of the text / landing — the stored text_direction
|
||||
// (UCS X for UCS-placed leaders, world X otherwise), so the whole text-side
|
||||
// layout follows the UCS instead of world horizontal.
|
||||
let (tdx, tdy) = {
|
||||
let td = ml.context.text_direction;
|
||||
let l = (td.x * td.x + td.y * td.y).sqrt();
|
||||
if l > 1e-9 {
|
||||
(td.x / l, td.y / l)
|
||||
} else {
|
||||
let a = ml.context.text_rotation;
|
||||
(a.cos(), a.sin())
|
||||
}
|
||||
};
|
||||
// Which side of the leader the text sits on, measured along that direction.
|
||||
let rel_dot = (text_loc.x - leader_ref.x) * tdx + (text_loc.y - leader_ref.y) * tdy;
|
||||
let text_sign: f64 = if rel_dot >= 0.0 { 1.0 } else { -1.0 };
|
||||
|
||||
// Lay the text out once, up front: its width fixes where the landing meets
|
||||
// the text. The same layout is reused below to emit the glyph strokes.
|
||||
|
|
@ -164,7 +175,11 @@ fn to_truck(ml: &MultiLeader, document: &acadrust::CadDocument) -> Option<TruckE
|
|||
};
|
||||
// text_location is the leader-facing (near) edge; the landing runs one
|
||||
// dogleg from there back toward the leader.
|
||||
let landing_pt = [text_loc.x - text_sign * dogleg, text_loc.y, text_loc.z];
|
||||
let landing_pt = [
|
||||
text_loc.x - text_sign * dogleg * tdx,
|
||||
text_loc.y - text_sign * dogleg * tdy,
|
||||
text_loc.z,
|
||||
];
|
||||
|
||||
for root in &ml.context.leader_roots {
|
||||
let cp = &root.connection_point;
|
||||
|
|
|
|||
Loading…
Reference in a new issue