Fillet Corners: the shared continuity control says what each corner builds

The Corners row keeps the control's words (Tangent, Curvature) and its hover text says what
each makes: a rolling-ball corner (G1), or a smooth patch set back along each edge by the
Setback, 1.5 × the radius when empty (G2). continuity_row_explained is the shared control with
a caller's hover text; the new lines are in en, ar, de, he, ja, ko and zh.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
jyviko
2026-10-27 21:02:23 -04:00
committed by Irakli Kourtis
parent fab8948b35
commit 1260353f48
3 changed files with 49 additions and 17 deletions
+21 -7
View File
@@ -1,30 +1,44 @@
{
"en": {
"ui.continuity_smooth_curvature_change": "Smooth curvature change",
"ui.continuity_smooth_curvature_change_tip": "Smooth curvature change (G4): even the way the curvature changes runs on smoothly across the seam."
"ui.continuity_smooth_curvature_change_tip": "Smooth curvature change (G4): even the way the curvature changes runs on smoothly across the seam.",
"ui.fillet_corner_tangent_tip": "Tangent (G1): a rolling-ball corner, a piece of the rolling ball's sphere tangent to each round.",
"ui.fillet_corner_curvature_tip": "Curvature (G2): a smooth patch. The corner is set back along each edge by the Setback (empty: {factor} × the radius) and filled with a patch, so reflections run through it without a kink."
},
"ar": {
"ui.continuity_smooth_curvature_change": "تغيّر انحناء سلس",
"ui.continuity_smooth_curvature_change_tip": "تغيّر انحناء سلس (G4): حتى طريقة تغيّر الانحناء تستمر بسلاسة عبر خط الالتقاء."
"ui.continuity_smooth_curvature_change_tip": "تغيّر انحناء سلس (G4): حتى طريقة تغيّر الانحناء تستمر بسلاسة عبر خط الالتقاء.",
"ui.fillet_corner_tangent_tip": "مماس (G1): زاوية بالكرة المتدحرجة، جزء من سطح الكرة المتدحرجة مماسّ لكل تقويس.",
"ui.fillet_corner_curvature_tip": "الانحناء (G2): رقعة ناعمة. تُرجَع الزاوية على طول كل حافة بمقدار الإرجاع (فارغ: {factor} ضعف نصف القطر) وتُملأ برقعة، فتمر الانعكاسات عبرها دون انكسار."
},
"de": {
"ui.continuity_smooth_curvature_change": "Glatte Krümmungsänderung",
"ui.continuity_smooth_curvature_change_tip": "Glatte Krümmungsänderung (G4): Selbst die Art, wie sich die Krümmung ändert, läuft an der Naht glatt weiter."
"ui.continuity_smooth_curvature_change_tip": "Glatte Krümmungsänderung (G4): Selbst die Art, wie sich die Krümmung ändert, läuft an der Naht glatt weiter.",
"ui.fillet_corner_tangent_tip": "Tangential (G1): eine Kugelecke, ein Stück der Kugel des rollenden Balls, tangential zu jeder Rundung.",
"ui.fillet_corner_curvature_tip": "Krümmung (G2): ein glattes Flächenstück. Die Ecke wird entlang jeder Kante um den Rücksprung zurückgesetzt (leer: {factor} × der Radius) und mit einem Flächenstück gefüllt, sodass Spiegelungen ohne Knick hindurchlaufen."
},
"he": {
"ui.continuity_smooth_curvature_change": "שינוי עקמומיות חלק",
"ui.continuity_smooth_curvature_change_tip": "שינוי עקמומיות חלק (G4): גם האופן שבו העקמומיות משתנה ממשיך בצורה חלקה לאורך התפר."
"ui.continuity_smooth_curvature_change_tip": "שינוי עקמומיות חלק (G4): גם האופן שבו העקמומיות משתנה ממשיך בצורה חלקה לאורך התפר.",
"ui.fillet_corner_tangent_tip": "משיק (G1): פינת כדור מתגלגל, חלק מספירת הכדור המתגלגל, משיק לכל עיגול.",
"ui.fillet_corner_curvature_tip": "עקמומיות (G2): טלאי חלק. הפינה נסוגה לאורך כל קצה במרחק הנסיגה (ריק: פי {factor} מהרדיוס) ומתמלאת בטלאי, כך שההשתקפויות עוברות בה בלי שבר."
},
"ja": {
"ui.continuity_smooth_curvature_change": "なめらかな曲率変化",
"ui.continuity_smooth_curvature_change_tip": "なめらかな曲率変化 (G4): 境目で曲率の変わり方そのものもなめらかに続きます。"
"ui.continuity_smooth_curvature_change_tip": "なめらかな曲率変化 (G4): 境目で曲率の変わり方そのものもなめらかに続きます。",
"ui.fillet_corner_tangent_tip": "接線 (G1): 転がるボールのコーナー。転がるボールの球面の一部で、各フィレットに接します。",
"ui.fillet_corner_curvature_tip": "曲率 (G2): なめらかなパッチ。コーナーを各エッジに沿ってセットバック分 (空欄のときは半径の {factor} 倍) 後退させてパッチで埋め、映り込みが折れずに通ります。"
},
"ko": {
"ui.continuity_smooth_curvature_change": "부드러운 곡률 변화",
"ui.continuity_smooth_curvature_change_tip": "부드러운 곡률 변화(G4): 이음매에서 곡률이 변하는 방식까지 부드럽게 이어집니다."
"ui.continuity_smooth_curvature_change_tip": "부드러운 곡률 변화(G4): 이음매에서 곡률이 변하는 방식까지 부드럽게 이어집니다.",
"ui.fillet_corner_tangent_tip": "접선(G1): 굴러가는 볼 코너. 굴러가는 볼의 구면 일부로, 각 라운드에 접합니다.",
"ui.fillet_corner_curvature_tip": "곡률(G2): 부드러운 패치. 코너를 각 모서리를 따라 셋백만큼(비워 두면 반지름의 {factor}배) 물려 패치로 채우므로, 반사가 꺾임 없이 지나갑니다."
},
"zh": {
"ui.continuity_smooth_curvature_change": "平滑曲率变化",
"ui.continuity_smooth_curvature_change_tip": "平滑曲率变化 (G4):连曲率的变化方式在接缝处也平滑延续。"
"ui.continuity_smooth_curvature_change_tip": "平滑曲率变化 (G4):连曲率的变化方式在接缝处也平滑延续。",
"ui.fillet_corner_tangent_tip": "相切 (G1):滚球角,滚球球面的一部分,与每个圆角相切。",
"ui.fillet_corner_curvature_tip": "曲率 (G2):平滑曲面片。角点沿每条边后退一个后退距离(留空:半径的 {factor} 倍),并用曲面片填充,反射穿过时没有折痕。"
}
}
+21 -9
View File
@@ -108,9 +108,19 @@ const FILLET_TYPES: [(&str, &str); 5] = [
("Spline", "spline"),
];
/// How a fillet's corners where three or more rounded edges meet continue the rounds: tangent (a
/// rolling ball, the `corner` default) or curvature continuous (`corner: g2`, a smooth patch).
const FILLET_CORNERS: [Continuity; 2] = [Continuity::G1, Continuity::G2];
/// How a fillet's corners where three or more rounded edges meet continue the rounds, with the
/// hover line that says what each builds: tangent (a rolling ball, the `corner` default) or
/// curvature continuous (`corner: g2`, a smooth patch set back along each edge).
const FILLET_CORNERS: [(Continuity, &str); 2] =
[(Continuity::G1, "ui.fillet_corner_tangent_tip"), (Continuity::G2, "ui.fillet_corner_curvature_tip")];
/// The default setback of a smooth-patch corner, as a multiple of the radius.
const SETBACK_FACTOR: &str = "1.5";
/// The Corners row's hover text: a line for each choice.
fn fillet_corner_tip() -> String {
FILLET_CORNERS.map(|(_, tip)| crate::i18n::format(tip, &[("factor", SETBACK_FACTOR)])).join("\n")
}
/// A fillet's Corners row (`corner`) and, with a smooth patch, its Setback (`setbacks`, one
/// distance for every corner). Shown only while the edges have a corner where three or more
@@ -132,7 +142,7 @@ fn fillet_corner_rows(
let mut enter = false;
ui.add_enabled_ui(rtype == 0 && exact, |ui| {
let mut corner = if patch { Continuity::G2 } else { Continuity::G1 };
ui_kit::continuity_row(ui, "ui.corners", "fi_corner", &mut corner, &FILLET_CORNERS);
ui_kit::continuity_row_explained(ui, "ui.corners", "fi_corner", &mut corner, &FILLET_CORNERS.map(|(g, _)| g), &fillet_corner_tip());
if (corner == Continuity::G2) != patch {
if corner == Continuity::G2 {
extra.insert("corner".into(), json!(Continuity::G2.as_str()));
@@ -142,11 +152,11 @@ fn fillet_corner_rows(
}
if extra.get("corner").and_then(Value::as_str) == Some("g2") {
ui.scope(|ui| {
let hint = crate::i18n::format("ui.fillet_setback_hint", &[("factor", "1.5")]);
let hint = crate::i18n::format("ui.fillet_setback_hint", &[("factor", SETBACK_FACTOR)]);
enter |= hint_row(ui, "ui.fillet_setback", setback, &hint);
})
.response
.on_hover_text(crate::i18n::format("ui.fillet_setback_tip", &[("factor", "1.5")]));
.on_hover_text(crate::i18n::format("ui.fillet_setback_tip", &[("factor", SETBACK_FACTOR)]));
}
})
.response
@@ -1208,12 +1218,14 @@ mod tests {
#[test]
fn fillet_labels_use_words_not_continuity_codes() {
let coded = |text: &str| ["G0", "G1", "G2", "G3"].iter().any(|code| text.contains(code));
for label in FILLET_TYPES.map(|(label, _)| label).into_iter().chain(FILLET_CORNERS.map(Continuity::label_id)) {
for label in FILLET_TYPES.map(|(label, _)| label).into_iter().chain(FILLET_CORNERS.map(|(g, _)| g.label_id())) {
assert!(!coded(crate::i18n::tr_label(label)), "{label}: {}", crate::i18n::tr_label(label));
}
for tip in FILLET_CORNERS.map(Continuity::tip_id) {
assert!(coded(crate::i18n::tr(tip)), "the hover text keeps the code for those who know it: {tip}");
for (g, tip) in FILLET_CORNERS {
assert!(crate::i18n::tr(tip).contains(g.code()), "the hover text keeps the code for those who know it: {tip}");
}
let tip = fillet_corner_tip();
assert!(tip.contains("rolling") && tip.contains("1.5") && tip.contains("Setback"), "what each corner builds: {tip}");
let mut h = fillet_harness();
set_edges(&mut h, 3);
choose(&mut h, "ui.corners", Continuity::G2.label_id());
+7 -1
View File
@@ -98,13 +98,19 @@ pub(crate) fn choice_row(ui: &mut Ui, label: &str, id: &str, selected: &mut usiz
/// plain words and its hover text a line per order naming its code, both from the kernel's one
/// table of orders; a value not in `allowed` shows the first. Tokens: `row, dropdown`.
pub(crate) fn continuity_row(ui: &mut Ui, label: &str, id: &str, value: &mut Continuity, allowed: &[Continuity]) -> Response {
continuity_row_explained(ui, label, id, value, allowed, &continuity_tip(allowed))
}
/// [`continuity_row`] whose hover text says what each order builds there (`tip`, which names
/// each order's code), for a choice whose orders stand for constructions (a fillet's corners).
pub(crate) fn continuity_row_explained(ui: &mut Ui, label: &str, id: &str, value: &mut Continuity, allowed: &[Continuity], tip: &str) -> Response {
let labels: Vec<&str> = allowed.iter().map(|g| g.label_id()).collect();
let mut index = allowed.iter().position(|g| g == value).unwrap_or(0);
let response = choice_row(ui, label, id, &mut index, &labels);
if let Some(g) = allowed.get(index) {
*value = *g;
}
response.on_hover_text(continuity_tip(allowed))
response.on_hover_text(tip)
}
/// The hover text of a continuity choice: each order's own line, which names its code.