diff --git a/assets/locales/pending/tap-drills.json b/assets/locales/pending/tap-drills.json index 591a54dfdb..985823c0f1 100644 --- a/assets/locales/pending/tap-drills.json +++ b/assets/locales/pending/tap-drills.json @@ -1,49 +1,35 @@ { "en": { - "prefs.holes": "Holes", - "prefs.metric_tap_drill_major_less_pitch": "Metric tapped holes drill the major diameter less the pitch (M8: 6.75 mm), not the tap maker's drill", "thread.drill_range": "The tap maker's drill is {drill} mm. The internal thread's standard minor diameter is {minor} mm. A drill from {low} to {high} mm is accepted.", "thread.drill_range_custom": "The drill is the major diameter less the pitch, {drill} mm. The internal thread's standard minor diameter is {minor} mm. A drill from {low} to {high} mm is accepted.", "thread.drill_range_taper": "The tap maker's drill is {drill} mm. The standard's minor diameter where the thread ends is {minor} mm. A drill from {low} to {high} mm is accepted." }, "ar": { - "prefs.holes": "الثقوب", - "prefs.metric_tap_drill_major_less_pitch": "تُثقب الثقوب الملولبة المترية بالقطر الأكبر ناقص الخطوة (M8: 6.75 مم) بدل مثقاب صانع اللقمة", "thread.drill_range": "مثقاب صانع اللقمة {drill} مم. القطر الأصغر القياسي للسن الداخلي {minor} مم. يُقبل مثقاب من {low} إلى {high} مم.", "thread.drill_range_custom": "المثقاب هو القطر الأكبر ناقص الخطوة، {drill} مم. القطر الأصغر القياسي للسن الداخلي {minor} مم. يُقبل مثقاب من {low} إلى {high} مم.", "thread.drill_range_taper": "مثقاب صانع اللقمة {drill} مم. القطر الأصغر القياسي عند نهاية السن {minor} مم. يُقبل مثقاب من {low} إلى {high} مم." }, "he": { - "prefs.holes": "חורים", - "prefs.metric_tap_drill_major_less_pitch": "חורים מתוברגים מטריים נקדחים בקוטר הגדול פחות הפסיעה (M8: 6.75 מ\"מ) ולא במקדח של יצרן המברז", "thread.drill_range": "מקדח יצרן המברז הוא {drill} מ\"מ. הקוטר הקטן התקני של התבריג הפנימי הוא {minor} מ\"מ. מתקבל מקדח מ-{low} עד {high} מ\"מ.", "thread.drill_range_custom": "המקדח הוא הקוטר הגדול פחות הפסיעה, {drill} מ\"מ. הקוטר הקטן התקני של התבריג הפנימי הוא {minor} מ\"מ. מתקבל מקדח מ-{low} עד {high} מ\"מ.", "thread.drill_range_taper": "מקדח יצרן המברז הוא {drill} מ\"מ. הקוטר הקטן התקני בסוף התבריג הוא {minor} מ\"מ. מתקבל מקדח מ-{low} עד {high} מ\"מ." }, "ja": { - "prefs.holes": "穴", - "prefs.metric_tap_drill_major_less_pitch": "メートルねじ穴の下穴を、タップメーカーの推奨値ではなく外径からピッチを引いた値にする(M8: 6.75 mm)", "thread.drill_range": "タップメーカーの下穴ドリルは {drill} mm です。めねじの規格の内径は {minor} mm です。{low}~{high} mm のドリルを使用できます。", "thread.drill_range_custom": "下穴ドリルは外径からピッチを引いた {drill} mm です。めねじの規格の内径は {minor} mm です。{low}~{high} mm のドリルを使用できます。", "thread.drill_range_taper": "タップメーカーの下穴ドリルは {drill} mm です。ねじ終端での規格の内径は {minor} mm です。{low}~{high} mm のドリルを使用できます。" }, "zh": { - "prefs.holes": "孔", - "prefs.metric_tap_drill_major_less_pitch": "公制螺纹孔的底孔取大径减螺距(M8:6.75 mm),而非丝锥制造商的钻头", "thread.drill_range": "丝锥制造商的钻头为 {drill} mm。内螺纹的标准小径为 {minor} mm。可使用 {low} 至 {high} mm 的钻头。", "thread.drill_range_custom": "钻头为大径减螺距,{drill} mm。内螺纹的标准小径为 {minor} mm。可使用 {low} 至 {high} mm 的钻头。", "thread.drill_range_taper": "丝锥制造商的钻头为 {drill} mm。螺纹终端处的标准小径为 {minor} mm。可使用 {low} 至 {high} mm 的钻头。" }, "de": { - "prefs.holes": "Bohrungen", - "prefs.metric_tap_drill_major_less_pitch": "Metrische Gewindebohrungen mit Nenndurchmesser minus Steigung bohren (M8: 6,75 mm), nicht mit dem Bohrer des Gewindebohrerherstellers", "thread.drill_range": "Der Bohrer des Gewindebohrerherstellers ist {drill} mm. Der genormte Kerndurchmesser des Innengewindes ist {minor} mm. Ein Bohrer von {low} bis {high} mm wird angenommen.", "thread.drill_range_custom": "Der Bohrer ist der Nenndurchmesser minus Steigung, {drill} mm. Der genormte Kerndurchmesser des Innengewindes ist {minor} mm. Ein Bohrer von {low} bis {high} mm wird angenommen.", "thread.drill_range_taper": "Der Bohrer des Gewindebohrerherstellers ist {drill} mm. Der genormte Kerndurchmesser am Gewindeende ist {minor} mm. Ein Bohrer von {low} bis {high} mm wird angenommen." }, "ko": { - "prefs.holes": "구멍", - "prefs.metric_tap_drill_major_less_pitch": "미터 탭 구멍을 탭 제조사의 드릴 대신 바깥지름에서 피치를 뺀 값으로 뚫기 (M8: 6.75 mm)", "thread.drill_range": "탭 제조사의 드릴은 {drill} mm입니다. 암나사의 규격 골지름은 {minor} mm입니다. {low}~{high} mm 드릴을 사용할 수 있습니다.", "thread.drill_range_custom": "드릴은 바깥지름에서 피치를 뺀 {drill} mm입니다. 암나사의 규격 골지름은 {minor} mm입니다. {low}~{high} mm 드릴을 사용할 수 있습니다.", "thread.drill_range_taper": "탭 제조사의 드릴은 {drill} mm입니다. 나사 끝에서의 규격 골지름은 {minor} mm입니다. {low}~{high} mm 드릴을 사용할 수 있습니다." diff --git a/crates/doc/src/thread_catalog.rs b/crates/doc/src/thread_catalog.rs index a3d0e394a9..642c8b44fc 100644 --- a/crates/doc/src/thread_catalog.rs +++ b/crates/doc/src/thread_catalog.rs @@ -485,16 +485,6 @@ impl TappedThread { (self.minor_diameter().min(self.tap_drill), self.tap_drill * (1.0 + DRILL_ALLOWANCE)) } - /// The drill a new hole of this size takes without a `diameter`: the tap maker's, or for an - /// ISO metric size with `major_less_pitch` (the preference that keeps the drill every metric - /// size took before) the major diameter less the pitch, to the micrometre. - pub fn default_drill(&self, major_less_pitch: bool) -> f64 { - match (self.family, major_less_pitch) { - (TappedThreadFamily::Metric, true) => ((self.major_diameter - self.pitch) * 1000.0).round() / 1000.0, - _ => self.tap_drill, - } - } - /// Whether a hole of `diameter` mm can be tapped to this size; the error names the range. pub fn check_drill(&self, diameter: f64) -> Result<(), String> { let (lo, hi) = self.drill_range(); diff --git a/crates/engine/src/cmd/features.rs b/crates/engine/src/cmd/features.rs index 99855d9ace..1729847255 100644 --- a/crates/engine/src/cmd/features.rs +++ b/crates/engine/src/cmd/features.rs @@ -2551,7 +2551,7 @@ fn hole(s: &mut Session, p: &Value) -> Result { } (None, Some(t), None) => { let size = solidcraft_doc::parse_tapped_thread(t).ok_or_else(|| bad(cmd, "thread"))?; - Expr::new(format!("{} mm", size.default_drill(s.metric_tap_drill_major_less_pitch))) + Expr::new(format!("{} mm", size.tap_drill)) } (None, None, None) => return Err(bad(cmd, "needs `diameter`, `thread` (a tapped hole) or `clearance` (a bolt size)")), }; diff --git a/crates/engine/src/lib.rs b/crates/engine/src/lib.rs index fc59770469..5d8fa083a4 100644 --- a/crates/engine/src/lib.rs +++ b/crates/engine/src/lib.rs @@ -377,9 +377,6 @@ pub struct Session { pub(crate) followed: Option, /// Project a face's edges into a sketch created on it (the default; `sketch.auto_project`). pub auto_project: bool, - /// A new metric tapped hole given no `diameter` drills the major diameter less the pitch, - /// as before the tap maker's drills (a user preference); false: the tap maker's drill. - pub metric_tap_drill_major_less_pitch: bool, /// A new symmetric surface extrude given no `convention` reads its distance on each side, as /// surface extrudes did before they matched solid ones (a user preference); false: the total, /// split evenly around the start plane, as a solid extrude reads it. @@ -651,7 +648,6 @@ impl Session { document_id: cmd::inspect::new_document_id(), followed: None, auto_project: true, - metric_tap_drill_major_less_pitch: false, surface_extrude_symmetric_per_side: false, param_check: schema::ParamCheck::Off, easyprint_upload: None, @@ -702,7 +698,6 @@ impl Session { pub fn replace_design(&mut self, fresh: Session) { let auto_project = self.auto_project; let validation = self.validation(); - let metric_tap_drill_major_less_pitch = self.metric_tap_drill_major_less_pitch; let surface_extrude_symmetric_per_side = self.surface_extrude_symmetric_per_side; let param_check = self.param_check; let easyprint_upload = self.easyprint_upload.take(); @@ -722,7 +717,6 @@ impl Session { // The user's, like `auto_project`: the commands that open a design evaluate it under it // already (`Session::opened_validating`). self.set_validation(validation); - self.metric_tap_drill_major_less_pitch = metric_tap_drill_major_less_pitch; self.surface_extrude_symmetric_per_side = surface_extrude_symmetric_per_side; self.param_check = param_check; self.easyprint_upload = easyprint_upload; @@ -1480,7 +1474,6 @@ impl Session { document_id: self.document_id.clone(), followed: None, auto_project: self.auto_project, - metric_tap_drill_major_less_pitch: self.metric_tap_drill_major_less_pitch, surface_extrude_symmetric_per_side: self.surface_extrude_symmetric_per_side, param_check: self.param_check, easyprint_upload: self.easyprint_upload.clone(), diff --git a/crates/engine/src/thread_tests.rs b/crates/engine/src/thread_tests.rs index 7a9fea1265..755a98a2c1 100644 --- a/crates/engine/src/thread_tests.rs +++ b/crates/engine/src/thread_tests.rs @@ -1268,3 +1268,21 @@ fn a_modelled_tapped_hole_stops_clear_of_its_bottom_or_fades_out_before_it() { assert!(drill(6.5).contains("the tap cannot cut")); assert!(drill(7.1).is_empty() && drill(6.7).is_empty(), "inside the range"); } + +/// A tapped hole given no `diameter` drills the tap maker's drill for its size (M8: 6.8 mm, 1/4-20 +/// UNC: 5.1054 mm); a given diameter is kept. +#[test] +fn a_tapped_hole_given_no_diameter_drills_the_tap_makers_drill() { + let mut s = Session::default(); + run(&mut s, "solid.box", json!({"length":40,"width":20,"height":10,"body_name":"Plate"})); + let mut drilled = |p: Value| { + let id = run(&mut s, "solid.hole", p)["feature"].as_u64().unwrap(); + match &s.doc.feature(id).unwrap().kind { + solidcraft_doc::FeatureKind::Hole { diameter, .. } => diameter.to_string(), + k => panic!("{k:?}"), + } + }; + assert_eq!(drilled(json!({"position":[10,10,10],"thread":"M8"})), "6.8 mm"); + assert_eq!(drilled(json!({"position":[25,10,10],"thread":"1/4-20 UNC"})), "5.1054 mm"); + assert_eq!(drilled(json!({"position":[33,10,10],"thread":"M8","diameter":"6.9 mm"})), "6.9 mm"); +} diff --git a/crates/ui-egui/src/dialogs_dense.rs b/crates/ui-egui/src/dialogs_dense.rs index 3bddd55747..77767212c2 100644 --- a/crates/ui-egui/src/dialogs_dense.rs +++ b/crates/ui-egui/src/dialogs_dense.rs @@ -631,14 +631,7 @@ pub(super) fn rows(app: &mut SolveApp, ctx: &egui::Context, d: &mut Dialog, ui: opts.tapped = tap == 1; }); if opts.tapped { - enter |= crate::dialogs_thread::hole_rows( - ui, - &app.session.doc, - &mut opts.thread, - &mut opts.custom_thread, - &mut opts.drill, - app.preferences.metric_tap_drill_major_less_pitch, - ); + enter |= crate::dialogs_thread::hole_rows(ui, &app.session.doc, &mut opts.thread, &mut opts.custom_thread, &mut opts.drill); crate::dialogs_thread::hole_hand_row(ui, &mut opts.hand); ui_kit::checkbox_grid(ui, &mut [("Full thread depth", &mut opts.thread_full_depth), ("Modeled", &mut opts.modeled)], 1); // A modelled thread's inner end, towards the bottom, as the thread dialog's. diff --git a/crates/ui-egui/src/dialogs_thread.rs b/crates/ui-egui/src/dialogs_thread.rs index b3cf414937..55f05a7811 100644 --- a/crates/ui-egui/src/dialogs_thread.rs +++ b/crates/ui-egui/src/dialogs_thread.rs @@ -74,7 +74,6 @@ pub(crate) fn hole_rows( designation: &mut String, custom: &mut Option, drill: &mut Option, - major_less_pitch: bool, ) -> bool { let before = designation.clone(); let designation_id = ui.make_persistent_id("hole_thread_designation"); @@ -170,13 +169,12 @@ pub(crate) fn hole_rows( form_row(ui, "Tap drill diameter", |ui| { match parse_tapped_thread(designation).filter(|_| custom.as_ref().is_none_or(|draft| draft.error.is_none())) { Some(size) => { - let default = format!("{} mm", size.default_drill(major_less_pitch)); + let default = format!("{} mm", size.tap_drill); let (lo, hi) = size.drill_range(); let mm = |v: f64| format!("{:.3}", v); - let args = - [("drill", mm(size.default_drill(major_less_pitch))), ("minor", mm(size.minor_diameter())), ("low", mm(lo)), ("high", mm(hi))]; + let args = [("drill", mm(size.tap_drill)), ("minor", mm(size.minor_diameter())), ("low", mm(lo)), ("high", mm(hi))]; let args: Vec<(&str, &str)> = args.iter().map(|(k, v)| (*k, v.as_str())).collect(); - let id = match (size.taper_drill().is_some(), size.drill_is_tabulated() && size.default_drill(major_less_pitch) == size.tap_drill) { + let id = match (size.taper_drill().is_some(), size.drill_is_tabulated()) { (true, _) => "thread.drill_range_taper", (false, true) => "thread.drill_range", (false, false) => "thread.drill_range_custom", @@ -984,7 +982,7 @@ mod contribution_tests { let doc = Document::default(); let _ = ctx.run_ui(Default::default(), |ui| { egui::Grid::new("hole_catalogue").show(ui, |ui| { - hole_rows(ui, &doc, &mut designation, &mut custom, &mut None, false); + hole_rows(ui, &doc, &mut designation, &mut custom, &mut None); }); }); assert_eq!(designation, original); @@ -1135,7 +1133,7 @@ mod contribution_tests { let doc = Document::default(); let _ = context.run_ui(Default::default(), |ui| { egui::Grid::new("authored_hole").show(ui, |ui| { - hole_rows(ui, &doc, &mut hole, &mut custom, &mut None, false); + hole_rows(ui, &doc, &mut hole, &mut custom, &mut None); }); }); assert_eq!(hole, original); diff --git a/crates/ui-egui/src/documents.rs b/crates/ui-egui/src/documents.rs index 8b9c351b5c..d6c3f565ba 100644 --- a/crates/ui-egui/src/documents.rs +++ b/crates/ui-egui/src/documents.rs @@ -158,7 +158,6 @@ fn swap_in(app: &mut SolveApp, mut slot: DocSlot) -> DocSlot { put_view(app, slot.view); // Preferences the session holds go with the user, not the tab (#680). app.session.auto_project = out.session.auto_project; - app.session.metric_tap_drill_major_less_pitch = out.session.metric_tap_drill_major_less_pitch; app.session.surface_extrude_symmetric_per_side = out.session.surface_extrude_symmetric_per_side; app.session.set_validation(out.session.validation()); // So does the host's pre-command check: every tab is held to it. diff --git a/crates/ui-egui/src/lib.rs b/crates/ui-egui/src/lib.rs index e467206210..7f44c95ac2 100644 --- a/crates/ui-egui/src/lib.rs +++ b/crates/ui-egui/src/lib.rs @@ -978,9 +978,8 @@ impl SolveApp { if matches!(id, "file.save_mesh" | "file.send_to_slicer") { solidcraft_engine::slicers::set_chosen_programs(&self.preferences.custom_slicers); } - // The preferences the hole and surface extrude commands read, current even before the - // next frame applies them. - self.session.metric_tap_drill_major_less_pitch = self.preferences.metric_tap_drill_major_less_pitch; + // The preference the surface extrude command reads, current even before the next frame + // applies it. self.session.surface_extrude_symmetric_per_side = self.preferences.surface_extrude_symmetric_per_side; self.session.set_validation(self.preferences.validation); let t0 = now_ms(); diff --git a/crates/ui-egui/src/prefs.rs b/crates/ui-egui/src/prefs.rs index 89fd87ba33..a37902fb5a 100644 --- a/crates/ui-egui/src/prefs.rs +++ b/crates/ui-egui/src/prefs.rs @@ -633,10 +633,6 @@ preference_settings! { /// Up/Down and the wheel over a focused value field step its plain number (`value_step`, /// #2320). Off by default: the keys move the text cursor and the wheel scrolls, as before. step_values: bool = false, PAGE_DESIGN => check_id("ui.step_values"); - /// New metric tapped holes drill the major diameter less the pitch (M8: 6.75 mm), as before - /// the tap maker's drills; off by default: the tap maker's drill (M8: 6.8 mm). Saved designs - /// keep the drill they stored either way. - metric_tap_drill_major_less_pitch: bool = false, PAGE_DESIGN => check_id("prefs.metric_tap_drill_major_less_pitch"); /// New symmetric surface extrudes go their distance each way, as before they matched solid /// extrudes; off by default: the distance is the total, split evenly around the start plane. /// Saved designs keep the reading they stored either way. @@ -1130,9 +1126,7 @@ fn defaults(app: &mut SolveApp, page: usize) { /// the interface scale. pub fn apply(app: &mut SolveApp, ctx: &egui::Context) { apply_network(&app.preferences); - // The hole command reads the metric tapped drill rule from the session, Surface Extrude its - // symmetric reading. - app.session.metric_tap_drill_major_less_pitch = app.preferences.metric_tap_drill_major_less_pitch; + // Surface Extrude reads its symmetric reading from the session. app.session.surface_extrude_symmetric_per_side = app.preferences.surface_extrude_symmetric_per_side; // The features computed from now on are checked as the preference says. app.session.set_validation(app.preferences.validation); @@ -2461,44 +2455,16 @@ mod tests { assert!(!solidcraft_engine::profile::enabled()); } - /// New metric tapped holes drill the tap maker's drill (M8: 6.8 mm); the preference keeps - /// the major diameter less the pitch they took before (6.75 mm). It reaches the hole command - /// whether set through the control channel or the Preferences page, and a hole given its - /// diameter keeps it either way. + /// Preferences saved with a setting this version no longer has still load, every other + /// setting kept: the removed key is ignored like any unknown one. #[test] - fn the_metric_tap_drill_preference_keeps_major_less_pitch() { + fn saved_preferences_with_a_removed_setting_still_load() { use serde_json::json; - let plate = || { - let mut h = crate::scenario::Harness::new(); - h.app.run("solid.box", json!({"length":40,"width":20,"height":10,"body_name":"Plate"})).unwrap(); - h - }; - let drilled = |h: &mut crate::scenario::Harness, params: serde_json::Value| { - let id = h.app.run("solid.hole", params).unwrap()["feature"].as_u64().unwrap(); - match &h.app.session.doc.feature(id).unwrap().kind { - solidcraft_engine::doc::FeatureKind::Hole { diameter, .. } => diameter.to_string(), - k => panic!("{k:?}"), - } - }; - let m8 = json!({"position":[10,10,10],"thread":"M8"}); - let mut h = plate(); - h.frames(1); - assert!(!h.app.preferences.metric_tap_drill_major_less_pitch, "off by default"); - assert_eq!(drilled(&mut h, m8.clone()), "6.8 mm"); - let mut h = plate(); - h.call("ui.prefs", json!({"metric_tap_drill_major_less_pitch": true})); - h.frames(2); - assert!(h.app.session.metric_tap_drill_major_less_pitch); - assert_eq!(drilled(&mut h, m8.clone()), "6.75 mm"); - // Only metric changes: a Unified size keeps its tabulated drill. - assert_eq!(drilled(&mut h, json!({"position":[25,10,10],"thread":"1/4-20 UNC"})), "5.1054 mm"); - let mut given = m8; - given["position"] = json!([33, 10, 10]); - given["diameter"] = json!("6.9 mm"); - assert_eq!(drilled(&mut h, given), "6.9 mm"); - // A design opened or started keeps the user's choice. - h.app.run("file.new", json!({})).unwrap(); - assert!(h.app.session.metric_tap_drill_major_less_pitch); + let saved = json!({"length_decimals": 4, "metric_tap_drill_major_less_pitch": true}); + let p = serde_json::from_value::(saved.clone()).unwrap(); + assert_eq!(p.length_decimals, 4); + assert_eq!(super::lenient(&saved).length_decimals, 4); + assert!(serde_json::to_value(&p).unwrap().get("metric_tap_drill_major_less_pitch").is_none(), "not written back"); } /// New symmetric surface extrudes read their distance as the total, as solid extrudes do; the diff --git a/crates/ui-egui/src/prefs/design.rs b/crates/ui-egui/src/prefs/design.rs index 6dbaea3b4a..a517926e2a 100644 --- a/crates/ui-egui/src/prefs/design.rs +++ b/crates/ui-egui/src/prefs/design.rs @@ -36,10 +36,6 @@ pub(super) fn show(app: &mut SolveApp, ui: &mut egui::Ui) { let step = setting::step_values(app, ui).on_hover_text(tip); crate::scenario::publish_handle("prefs:step_values", step.rect.center()); }); - ui_kit::settings_section(ui, "holes", app.tr("prefs.holes"), |ui| { - let check = setting::metric_tap_drill_major_less_pitch(app, ui); - crate::scenario::publish_handle("prefs:metric_tap_drill_major_less_pitch", check.rect.center()); - }); ui_kit::settings_section(ui, "surfaces", app.tr("prefs.surfaces"), |ui| { let check = setting::surface_extrude_symmetric_per_side(app, ui); crate::scenario::publish_handle("prefs:surface_extrude_symmetric_per_side", check.rect.center()); diff --git a/docs/thread-catalogue.md b/docs/thread-catalogue.md index 16c5787a81..fee88c67cf 100644 --- a/docs/thread-catalogue.md +++ b/docs/thread-catalogue.md @@ -27,10 +27,6 @@ cutting taps, printed p.704 (M, coarse) and pp.704 to 706 (MF, fine); M8 drills the pitch, to 0.001 mm (M8.5x1: 7.5 mm). This replaces the major-minus-pitch estimate every metric size took before (M8 6.75 mm). A saved design keeps the diameter it stored, so it builds as before; editing such a hole keeps its drill. -The Design preference "Metric tapped holes drill the major diameter less the -pitch" (`metric_tap_drill_major_less_pitch`, off by default) gives new metric -holes that older drill again, in the Hole dialog and for the `solid.hole` command -given no `diameter`. Custom metric dimensions remain editable, and Custom stays selected even when its current dimensions match a catalogue entry.