diff --git a/Cargo.lock b/Cargo.lock index 5b9999644..11779fe05 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -72,7 +72,7 @@ checksum = "366ffbaa4442f4684d91e2cd7c5ea7c4ed8add41959a31447066e279e432b618" [[package]] name = "acadrust" version = "0.4.1" -source = "git+https://git@github.com/HakanSeven12/cadcodec.git?rev=711be3b#711be3b5151e25e7ed9931f37b0f7c4f16c0243d" +source = "git+https://git@github.com/HakanSeven12/cadcodec.git?rev=0f746f7#0f746f78ca871fded0e910b758d787eb9d4e74f8" dependencies = [ "ahash 0.8.12", "anyhow", diff --git a/Cargo.toml b/Cargo.toml index b6426a7ec..9e1bb9397 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,7 +27,7 @@ glam = { version = "0.33", features = ["bytemuck"] } rfd = "0.17" clap = { version = "4", features = ["derive"] } env_logger = "0.11" -acadrust = { git = "https://github.com/HakanSeven12/cadcodec.git", rev = "711be3b", features = ["serde"] } +acadrust = { git = "https://github.com/HakanSeven12/cadcodec.git", rev = "0f746f7", features = ["serde"] } cadkernel = { git = "https://github.com/HakanSeven12/cadkernel.git", rev = "b2b1d4b", features = ["acis", "offset"] } dwg-thumbnailer = { path = "crates/dwg-thumbnailer" } flate2 = "1" @@ -61,7 +61,7 @@ iced_core = { git = "https://github.com/iced-rs/iced.git", rev = "23604ff22ab0aa iced_widget = { git = "https://github.com/iced-rs/iced.git", rev = "23604ff22ab0aad9e00b9327cb7b8546ed84db39" } [patch."https://github.com/HakanSeven12/cadcodec.git"] -acadrust = { git = "https://git@github.com/HakanSeven12/cadcodec.git", rev = "711be3b" } +acadrust = { git = "https://git@github.com/HakanSeven12/cadcodec.git", rev = "0f746f7" } [target.'cfg(not(target_arch = "wasm32"))'.dependencies] ocs_plugin_api = { path = "crates/ocs_plugin_api", features = ["host"] } diff --git a/locales/ar-SA/opencadstudio.ftl b/locales/ar-SA/opencadstudio.ftl index f546f620b..3660ca438 100644 --- a/locales/ar-SA/opencadstudio.ftl +++ b/locales/ar-SA/opencadstudio.ftl @@ -1837,8 +1837,8 @@ annotate = .dimcontinue-no-base-dimension-found-place-a-di = DIMCONTINUE لم يُعثر على بُعد أساسي. ضع بُعدًا أولًا. .dimcontinue-specify-a-second-extension-line-or = DIMCONTINUE حدد أصل خط امتداد ثانٍ (Enter للخروج): .dimdiameter-enter-dimension-text-blank-measure = DIMDIAMETER أدخل نص البُعد (فارغ = القيمة المقاسة): - .dimdiameter-specify-center-point = DIMDIAMETER حدد نقطة المركز: - .dimdiameter-specify-dimension-line-location-te = DIMDIAMETER حدد موقع خط البُعد [نص/زاوية]: + .dimdiameter-select-arc-circle-or-polyline-arc = DIMDIAMETER حدد قوسًا أو دائرة أو قوسًا متعدد الخطوط: + .dimdiameter-specify-dimension-line-location-text = DIMDIAMETER حدد موقع خط البُعد [نص متعدد الأسطر/نص/زاوية]: .dimdiameter-specify-point-on-circle = DIMDIAMETER حدد نقطة على الدائرة: .dimdiameter-specify-text-angle-degrees = DIMDIAMETER حدد زاوية النص (بالدرجات): .dimedit-enter-text-override-blank-reset-to-mea = DIMEDIT أدخل نص التجاوز (فارغ = إعادة للقيمة المقاسة): diff --git a/locales/bg-BG/opencadstudio.ftl b/locales/bg-BG/opencadstudio.ftl index eb154aa29..d26b612b7 100644 --- a/locales/bg-BG/opencadstudio.ftl +++ b/locales/bg-BG/opencadstudio.ftl @@ -1824,8 +1824,8 @@ annotate = .dimcontinue-no-base-dimension-found-place-a-di = DIMCONTINUE Не е намерено базово оразмеряване. Първо постави оразмеряване. .dimcontinue-specify-a-second-extension-line-or = DIMCONTINUE Посочи начало на втора удължителна линия (Enter за изход): .dimdiameter-enter-dimension-text-blank-measure = DIMDIAMETER Въведи текст на оразмеряване (празно = измерена стойност): - .dimdiameter-specify-center-point = DIMDIAMETER Посочи централна точка: - .dimdiameter-specify-dimension-line-location-te = DIMDIAMETER Посочи местоположение на линията за оразмеряване [Текст/Ъгъл]: + .dimdiameter-select-arc-circle-or-polyline-arc = DIMDIAMETER Избери дъга, окръжност или дъгов сегмент на полилиния: + .dimdiameter-specify-dimension-line-location-text = DIMDIAMETER Посочи местоположение на линията за оразмеряване [Мтекст/Текст/Ъгъл]: .dimdiameter-specify-point-on-circle = DIMDIAMETER Посочи точка на окръжност: .dimdiameter-specify-text-angle-degrees = DIMDIAMETER Посочи ъгъл на текста (градуси): .dimedit-enter-text-override-blank-reset-to-mea = DIMEDIT Въведи заместващ текст (празно = върни към измерена стойност): diff --git a/locales/cs-CZ/opencadstudio.ftl b/locales/cs-CZ/opencadstudio.ftl index ef7c7b0f0..1db1ceb65 100644 --- a/locales/cs-CZ/opencadstudio.ftl +++ b/locales/cs-CZ/opencadstudio.ftl @@ -1824,8 +1824,8 @@ annotate = .dimcontinue-no-base-dimension-found-place-a-di = DIMCONTINUE Nebyl nalezen žádný rozměr základny. Nejprve umístěte kótu. .dimcontinue-specify-a-second-extension-line-or = DIMCONTINUE Zadejte počátek druhé prodlužovací čáry (Enter pro ukončení): .dimdiameter-enter-dimension-text-blank-measure = Text rozměru DIMDIAMETER Enter (prázdná naměřená hodnota =): - .dimdiameter-specify-center-point = DIMDIAMETER Zadejte středový bod: - .dimdiameter-specify-dimension-line-location-te = DIMDIAMETER Určete umístění kótovací čáry [Text/Úhel]: + .dimdiameter-select-arc-circle-or-polyline-arc = DIMDIAMETER Vyberte oblouk, kružnici nebo obloukový segment křivky: + .dimdiameter-specify-dimension-line-location-text = DIMDIAMETER Určete umístění kótovací čáry [MText/Text/Úhel]: .dimdiameter-specify-point-on-circle = DIMDIAMETER Určete bod na kružnici: .dimdiameter-specify-text-angle-degrees = DIMDIAMETER Zadejte úhel textu (stupně): .dimedit-enter-text-override-blank-reset-to-mea = Přepsání textu DIMEDIT Enter (prázdné = resetováno na měření): diff --git a/locales/de-DE/opencadstudio.ftl b/locales/de-DE/opencadstudio.ftl index a6b0c7750..151aec503 100644 --- a/locales/de-DE/opencadstudio.ftl +++ b/locales/de-DE/opencadstudio.ftl @@ -1825,8 +1825,8 @@ annotate = .dimcontinue-no-base-dimension-found-place-a-di = DIMCONTINUE Keine Basisdimension gefunden. .dimcontinue-specify-a-second-extension-line-or = DIMCONTINUE Ursprung der zweiten Maßhilfslinie angeben (Eingabe zum Beenden): .dimdiameter-enter-dimension-text-blank-measure = DIMDIAMETER Bemaßungstext eingeben (leer = Messwert): - .dimdiameter-specify-center-point = DIMDIAMETER Mittelpunkt angeben: - .dimdiameter-specify-dimension-line-location-te = DIMDIAMETER Lage der Dimensionslinie angeben [Text/Winkel]: + .dimdiameter-select-arc-circle-or-polyline-arc = DIMDIAMETER Bogen, Kreis oder Polylinienbogen auswählen: + .dimdiameter-specify-dimension-line-location-text = DIMDIAMETER Lage der Dimensionslinie angeben [MText/Text/Winkel]: .dimdiameter-specify-point-on-circle = DIMDIAMETER Punkt auf dem Kreis angeben: .dimdiameter-specify-text-angle-degrees = DIMDIAMETER Textwinkel angeben (Grad): .dimedit-enter-text-override-blank-reset-to-mea = DIMEDIT Textüberschreiben eingeben (leer = auf gemessen zurücksetzen): diff --git a/locales/en-US/opencadstudio.ftl b/locales/en-US/opencadstudio.ftl index cefa4e5e0..90ddec99d 100644 --- a/locales/en-US/opencadstudio.ftl +++ b/locales/en-US/opencadstudio.ftl @@ -1855,8 +1855,8 @@ annotate = .dimcontinue-no-base-dimension-found-place-a-di = DIMCONTINUE No base dimension found. Place a dimension first. .dimcontinue-specify-a-second-extension-line-or = DIMCONTINUE Specify a second extension line origin (Enter to exit): .dimdiameter-enter-dimension-text-blank-measure = DIMDIAMETER Enter dimension text (blank = measured value): - .dimdiameter-specify-center-point = DIMDIAMETER Specify center point: - .dimdiameter-specify-dimension-line-location-te = DIMDIAMETER Specify dimension line location [Text/Angle]: + .dimdiameter-select-arc-circle-or-polyline-arc = DIMDIAMETER Select arc, circle, or polyline arc: + .dimdiameter-specify-dimension-line-location-text = DIMDIAMETER Specify dimension line location [Mtext/Text/Angle]: .dimdiameter-specify-point-on-circle = DIMDIAMETER Specify point on circle: .dimdiameter-specify-text-angle-degrees = DIMDIAMETER Specify text angle (degrees): .dimedit-enter-text-override-blank-reset-to-mea = DIMEDIT Enter text override (blank = reset to measured): diff --git a/locales/es-ES/opencadstudio.ftl b/locales/es-ES/opencadstudio.ftl index 34d4f9800..3cbb886a6 100644 --- a/locales/es-ES/opencadstudio.ftl +++ b/locales/es-ES/opencadstudio.ftl @@ -1825,8 +1825,8 @@ annotate = .dimcontinue-no-base-dimension-found-place-a-di = DIMCONTINUE No se encontró ninguna cota base. Coloque primero una cota. .dimcontinue-specify-a-second-extension-line-or = DIMCONTINUE Especifique el origen de una segunda línea de referencia (Enter para salir): .dimdiameter-enter-dimension-text-blank-measure = DIMDIAMETER Introduzca el texto de cota (vacío = valor medido): - .dimdiameter-specify-center-point = DIMDIAMETER Especifique el centro: - .dimdiameter-specify-dimension-line-location-te = DIMDIAMETER Especifique la ubicación de la línea de cota [Texto/Ángulo]: + .dimdiameter-select-arc-circle-or-polyline-arc = DIMDIAMETER Seleccione un arco, círculo o arco de polilínea: + .dimdiameter-specify-dimension-line-location-text = DIMDIAMETER Especifique la ubicación de la línea de cota [Mtexto/Texto/Ángulo]: .dimdiameter-specify-point-on-circle = DIMDIAMETER Especifique un punto del círculo: .dimdiameter-specify-text-angle-degrees = DIMDIAMETER Especifique el ángulo del texto (grados): .dimedit-enter-text-override-blank-reset-to-mea = DIMEDIT Introduzca la sustitución de texto (vacío = restablecer al valor medido): diff --git a/locales/fi-FI/opencadstudio.ftl b/locales/fi-FI/opencadstudio.ftl index ac118187d..7eeb3327e 100644 --- a/locales/fi-FI/opencadstudio.ftl +++ b/locales/fi-FI/opencadstudio.ftl @@ -1824,8 +1824,8 @@ annotate = .dimcontinue-no-base-dimension-found-place-a-di = DIMCONTINUE Perusmittaa ei löytynyt. Aseta ensin mitta. .dimcontinue-specify-a-second-extension-line-or = DIMCONTINUE Määritä toinen alalinjan lähtökohta (Enter poistuaksesi): .dimdiameter-enter-dimension-text-blank-measure = DIMDIAMETER Enter mittateksti (tyhjä = mitattu arvo): - .dimdiameter-specify-center-point = DIMDIAMETER Määritä keskipiste: - .dimdiameter-specify-dimension-line-location-te = DIMDIAMETER Määritä mittaviivan sijainti [teksti/kulma]: + .dimdiameter-select-arc-circle-or-polyline-arc = DIMDIAMETER Valitse kaari, ympyrä tai murtoviivan kaari: + .dimdiameter-specify-dimension-line-location-text = DIMDIAMETER Määritä mittaviivan sijainti [Mteksti/teksti/kulma]: .dimdiameter-specify-point-on-circle = DIMDIAMETER Määritä piste ympyrässä: .dimdiameter-specify-text-angle-degrees = DIMDIAMETER Määritä tekstin kulma (asteita): .dimedit-enter-text-override-blank-reset-to-mea = DIMEDIT Enter tekstin ohitus (tyhjä = nollattu mitattuun): diff --git a/locales/fr-FR/opencadstudio.ftl b/locales/fr-FR/opencadstudio.ftl index 877df641c..389a696ef 100644 --- a/locales/fr-FR/opencadstudio.ftl +++ b/locales/fr-FR/opencadstudio.ftl @@ -1825,8 +1825,8 @@ annotate = .dimcontinue-no-base-dimension-found-place-a-di = DIMCONTINUE Aucune cote de base trouvée. Créez d’abord une cote. .dimcontinue-specify-a-second-extension-line-or = DIMCONTINUE Spécifiez une deuxième ligne d'extension d'origine (Entrer pour sortir): .dimdiameter-enter-dimension-text-blank-measure = DIMDIAMETER Entrer le texte dimensionnel (blanc = valeur mesurée): - .dimdiameter-specify-center-point = DIMDIAMETER Spécifier le point central: - .dimdiameter-specify-dimension-line-location-te = DIMDIAMETER Spécifiez la position de la ligne de cote [Texte / Angle] : + .dimdiameter-select-arc-circle-or-polyline-arc = DIMDIAMETER Sélectionnez un arc, un cercle ou un arc de polyligne : + .dimdiameter-specify-dimension-line-location-text = DIMDIAMETER Spécifiez la position de la ligne de cote [Mtexte/Texte/Angle] : .dimdiameter-specify-point-on-circle = DIMDIAMETER Spécifier le point sur le cercle: .dimdiameter-specify-text-angle-degrees = DIMDIAMETER Spécifiez l'angle de texte (degrés): .dimedit-enter-text-override-blank-reset-to-mea = DIMEDIT Saisissez la valeur de la valeur de remplacement (blank = reset to meased): diff --git a/locales/hi-IN/opencadstudio.ftl b/locales/hi-IN/opencadstudio.ftl index 89c986b2e..d42422685 100644 --- a/locales/hi-IN/opencadstudio.ftl +++ b/locales/hi-IN/opencadstudio.ftl @@ -1813,8 +1813,8 @@ annotate = .dimcontinue-no-base-dimension-found-place-a-di = DIMCONTINUE कोई आधार आयाम नहीं मिला। पहले आयाम दें। .dimcontinue-specify-a-second-extension-line-or = DIMCONTINUE एक दूसरी विस्तार लाइन मूल निर्दिष्ट करें (बाहर निकलने के लिए बेहतर): .dimdiameter-enter-dimension-text-blank-measure = DIMDIAMETER आयाम टेक्स्ट दर्ज करें (blank = मापा मान): - .dimdiameter-specify-center-point = DIMDIAMETER केंद्र बिंदु निर्दिष्ट करें: - .dimdiameter-specify-dimension-line-location-te = DIMDIAMETER आयाम लाइन स्थान निर्दिष्ट करें [टेक्स्ट / एंगल]: + .dimdiameter-select-arc-circle-or-polyline-arc = DIMDIAMETER आर्क, सर्कल या पॉलीलाइन आर्क चुनें: + .dimdiameter-specify-dimension-line-location-text = DIMDIAMETER आयाम लाइन स्थान निर्दिष्ट करें [एमटेक्स्ट/टेक्स्ट/एंगल]: .dimdiameter-specify-point-on-circle = DIMDIAMETER सर्कल पर बिंदु निर्दिष्ट करें: .dimdiameter-specify-text-angle-degrees = DIMDIAMETER पाठ कोण निर्दिष्ट करें (डिग्री): .dimedit-enter-text-override-blank-reset-to-mea = DIMEDIT टेक्स्ट ओवरराइड (ब्लैंक = मापा गया करने के लिए रीसेट): diff --git a/locales/hu-HU/opencadstudio.ftl b/locales/hu-HU/opencadstudio.ftl index 1ce1a22d9..6aa9ef22d 100644 --- a/locales/hu-HU/opencadstudio.ftl +++ b/locales/hu-HU/opencadstudio.ftl @@ -1824,8 +1824,8 @@ annotate = .dimcontinue-no-base-dimension-found-place-a-di = DIMCONTINUE Nem található alapméret. Először helyezzen el egy méretet. .dimcontinue-specify-a-second-extension-line-or = DIMCONTINUE Adjon meg egy második mellékvonal kezdőpontját (Enter a kilépéshez): .dimdiameter-enter-dimension-text-blank-measure = DIMDIAMETER Enter méretszöveg (üres = mért érték): - .dimdiameter-specify-center-point = DIMDIAMETER Középpont megadása: - .dimdiameter-specify-dimension-line-location-te = DIMDIAMETER A méretvonal helyének megadása [szöveg/szög]: + .dimdiameter-select-arc-circle-or-polyline-arc = DIMDIAMETER Válasszon ívet, kört vagy vonalláncívet: + .dimdiameter-specify-dimension-line-location-text = DIMDIAMETER A méretvonal helyének megadása [Mszöveg/szöveg/szög]: .dimdiameter-specify-point-on-circle = DIMDIAMETER Pont megadása a körön: .dimdiameter-specify-text-angle-degrees = DIMDIAMETER Adja meg a szöveg szögét (fokban): .dimedit-enter-text-override-blank-reset-to-mea = DIMEDIT Enter szöveg felülírása (üres = visszaállítása mért értékre): diff --git a/locales/it-IT/opencadstudio.ftl b/locales/it-IT/opencadstudio.ftl index 814c1f5a1..38b76b023 100644 --- a/locales/it-IT/opencadstudio.ftl +++ b/locales/it-IT/opencadstudio.ftl @@ -1824,8 +1824,8 @@ annotate = .dimcontinue-no-base-dimension-found-place-a-di = DIMCONTINUE Nessuna dimensione base trovata. Posiziona prima una dimensione. .dimcontinue-specify-a-second-extension-line-or = DIMCONTINUE Specificare una seconda origine della linea di estensione (Enter per uscire): .dimdiameter-enter-dimension-text-blank-measure = Testo della dimensione DIMDIAMETER Enter (valore misurato = vuoto): - .dimdiameter-specify-center-point = DIMDIAMETER Specificare il punto centrale: - .dimdiameter-specify-dimension-line-location-te = DIMDIAMETER Specificare la posizione della linea di quota [Testo/Angolo]: + .dimdiameter-select-arc-circle-or-polyline-arc = DIMDIAMETER Selezionare un arco, un cerchio o un arco di polilinea: + .dimdiameter-specify-dimension-line-location-text = DIMDIAMETER Specificare la posizione della linea di quota [Mtesto/Testo/Angolo]: .dimdiameter-specify-point-on-circle = DIMDIAMETER Specificare il punto sul cerchio: .dimdiameter-specify-text-angle-degrees = DIMDIAMETER Specificare l'angolo del testo (gradi): .dimedit-enter-text-override-blank-reset-to-mea = DIMEDIT Enter sovrascrittura testo (= vuoto ripristinato su misurato): diff --git a/locales/ja-JP/opencadstudio.ftl b/locales/ja-JP/opencadstudio.ftl index 605f2fddc..0f95f1f11 100644 --- a/locales/ja-JP/opencadstudio.ftl +++ b/locales/ja-JP/opencadstudio.ftl @@ -1815,8 +1815,8 @@ annotate = .dimcontinue-no-base-dimension-found-place-a-di = DIMCONTINUE 基準寸法がありません。先に寸法を配置してください。 .dimcontinue-specify-a-second-extension-line-or = DIMCONTINUE 2 本目の寸法補助線の起点を指定(Enter で終了): .dimdiameter-enter-dimension-text-blank-measure = DIMDIAMETER 寸法値を入力(空白 = 計測値): - .dimdiameter-specify-center-point = DIMDIAMETER 中心点を指定: - .dimdiameter-specify-dimension-line-location-te = DIMDIAMETER 寸法線の位置を指定 [文字/角度]: + .dimdiameter-select-arc-circle-or-polyline-arc = DIMDIAMETER 円弧、円、またはポリライン円弧を選択: + .dimdiameter-specify-dimension-line-location-text = DIMDIAMETER 寸法線の位置を指定 [マルチテキスト/文字/角度]: .dimdiameter-specify-point-on-circle = DIMDIAMETER 円上の点を指定: .dimdiameter-specify-text-angle-degrees = DIMDIAMETER 文字角度を指定(度): .dimedit-enter-text-override-blank-reset-to-mea = DIMEDIT 寸法値の上書きを入力(空白 = 計測値に戻す): diff --git a/locales/ko-KR/opencadstudio.ftl b/locales/ko-KR/opencadstudio.ftl index 05b50f338..5e72174ff 100644 --- a/locales/ko-KR/opencadstudio.ftl +++ b/locales/ko-KR/opencadstudio.ftl @@ -1824,8 +1824,8 @@ annotate = .dimcontinue-no-base-dimension-found-place-a-di = DIMCONTINUE 기본 치수를 찾을 수 없습니다. 먼저 치수를 배치합니다. .dimcontinue-specify-a-second-extension-line-or = DIMCONTINUE 두 번째 연장선 원점을 지정합니다(종료하려면 Enter). .dimdiameter-enter-dimension-text-blank-measure = DIMDIAMETER Enter 치수 문자(빈 = 측정 값): - .dimdiameter-specify-center-point = DIMDIAMETER 중심점 지정: - .dimdiameter-specify-dimension-line-location-te = DIMDIAMETER 치수선 위치 지정 [문자/각도]: + .dimdiameter-select-arc-circle-or-polyline-arc = DIMDIAMETER 호, 원 또는 폴리선 호 선택: + .dimdiameter-specify-dimension-line-location-text = DIMDIAMETER 치수선 위치 지정 [여러 줄 문자/문자/각도]: .dimdiameter-specify-point-on-circle = DIMDIAMETER 원의 점 지정: .dimdiameter-specify-text-angle-degrees = DIMDIAMETER 텍스트 각도(도) 지정: .dimedit-enter-text-override-blank-reset-to-mea = DIMEDIT Enter 텍스트 재정의(빈 =가 측정으로 재설정됨): diff --git a/locales/nl-NL/opencadstudio.ftl b/locales/nl-NL/opencadstudio.ftl index ca8ac95ca..f2a0dd41b 100644 --- a/locales/nl-NL/opencadstudio.ftl +++ b/locales/nl-NL/opencadstudio.ftl @@ -1825,8 +1825,8 @@ annotate = .dimcontinue-no-base-dimension-found-place-a-di = DIMCONTINUE Geen basismaat gevonden. Plaats eerst een maat. .dimcontinue-specify-a-second-extension-line-or = DIMCONTINUE Vermeld een tweede extensielijn (tot afsluiten overgaan): .dimdiameter-enter-dimension-text-blank-measure = DIMDIAMETER Voer maattekst in (leeg = gemeten waarde): - .dimdiameter-specify-center-point = DIMDIAMETER Centrumpunt opgeven: - .dimdiameter-specify-dimension-line-location-te = DIMDIAMETER Geef de positie van de maatlijn op [Tekst/Hoek]: + .dimdiameter-select-arc-circle-or-polyline-arc = DIMDIAMETER Selecteer boog, cirkel of polylijnboog: + .dimdiameter-specify-dimension-line-location-text = DIMDIAMETER Geef de positie van de maatlijn op [M-tekst/Tekst/Hoek]: .dimdiameter-specify-point-on-circle = DIMDIAMETER Punt op cirkel specificeren: .dimdiameter-specify-text-angle-degrees = DIMDIAMETER Teksthoek (graden) specificeren: .dimedit-enter-text-override-blank-reset-to-mea = DIMEDIT Tekstoverride invoeren (blanc = reset op gemeten): diff --git a/locales/pl-PL/opencadstudio.ftl b/locales/pl-PL/opencadstudio.ftl index aadb8ef21..0459de378 100644 --- a/locales/pl-PL/opencadstudio.ftl +++ b/locales/pl-PL/opencadstudio.ftl @@ -1824,8 +1824,8 @@ annotate = .dimcontinue-no-base-dimension-found-place-a-di = DIMCONTINUE Nie znaleziono wymiaru podstawowego. Najpierw umieść wymiar. .dimcontinue-specify-a-second-extension-line-or = DIMCONTINUE Określ początek drugiej linii pomocniczej (Enter, aby wyjść): .dimdiameter-enter-dimension-text-blank-measure = DIMDIAMETER Enter tekst wymiarowy (pusta wartość zmierzona =): - .dimdiameter-specify-center-point = DIMDIAMETER Określ punkt środkowy: - .dimdiameter-specify-dimension-line-location-te = DIMDIAMETER Określ położenie linii wymiarowej [Tekst/Kąt]: + .dimdiameter-select-arc-circle-or-polyline-arc = DIMDIAMETER Wybierz łuk, okrąg lub łuk polilinii: + .dimdiameter-specify-dimension-line-location-text = DIMDIAMETER Określ położenie linii wymiarowej [Mtekst/Tekst/Kąt]: .dimdiameter-specify-point-on-circle = DIMDIAMETER Określ punkt na okręgu: .dimdiameter-specify-text-angle-degrees = DIMDIAMETER Określ kąt tekstu (w stopniach): .dimedit-enter-text-override-blank-reset-to-mea = DIMEDIT Enter zastąpienie tekstu (puste = resetowane do zmierzonego): diff --git a/locales/pt-BR/opencadstudio.ftl b/locales/pt-BR/opencadstudio.ftl index b0fe5868e..3e939541f 100644 --- a/locales/pt-BR/opencadstudio.ftl +++ b/locales/pt-BR/opencadstudio.ftl @@ -1825,8 +1825,8 @@ annotate = .dimcontinue-no-base-dimension-found-place-a-di = DIMCONTINUE Nenhuma cota base encontrada. Coloque uma cota primeiro. .dimcontinue-specify-a-second-extension-line-or = DIMCONTINUE Especifique a origem de uma segunda linha de extensão (Enter para sair): .dimdiameter-enter-dimension-text-blank-measure = DIMDIAMETER Insira o texto da cota (vazio = valor medido): - .dimdiameter-specify-center-point = DIMDIAMETER Especifique o ponto central: - .dimdiameter-specify-dimension-line-location-te = DIMDIAMETER Especifique a localização da linha de cota [Texto/Ângulo]: + .dimdiameter-select-arc-circle-or-polyline-arc = DIMDIAMETER Selecione um arco, círculo ou arco de polilinha: + .dimdiameter-specify-dimension-line-location-text = DIMDIAMETER Especifique a localização da linha de cota [Mtexto/Texto/Ângulo]: .dimdiameter-specify-point-on-circle = DIMDIAMETER Especifique um ponto no círculo: .dimdiameter-specify-text-angle-degrees = DIMDIAMETER Especifique o ângulo do texto (graus): .dimedit-enter-text-override-blank-reset-to-mea = DIMEDIT Insira a substituição do texto (vazio = restaurar ao medido): diff --git a/locales/ru-RU/opencadstudio.ftl b/locales/ru-RU/opencadstudio.ftl index 3846025b8..fde73e1ed 100644 --- a/locales/ru-RU/opencadstudio.ftl +++ b/locales/ru-RU/opencadstudio.ftl @@ -1828,8 +1828,8 @@ annotate = .dimcontinue-no-base-dimension-found-place-a-di = DIMCONTINUE Базовый размер не найден. Сначала создайте размер. .dimcontinue-specify-a-second-extension-line-or = DIMCONTINUE Укажите происхождение второй линии расширения (Введите для выхода): .dimdiameter-enter-dimension-text-blank-measure = DIMDIAMETER Введите текст размера (пусто = измеренное значение): - .dimdiameter-specify-center-point = DIMDIAMETER Укажите центральную точку: - .dimdiameter-specify-dimension-line-location-te = DIMDIAMETER Укажите положение размерной линии [Текст/Угол]: + .dimdiameter-select-arc-circle-or-polyline-arc = DIMDIAMETER Выберите дугу, окружность или дуговой сегмент полилинии: + .dimdiameter-specify-dimension-line-location-text = DIMDIAMETER Укажите положение размерной линии [Мтекст/Текст/Угол]: .dimdiameter-specify-point-on-circle = DIMDIAMETER Укажите точку на окружности: .dimdiameter-specify-text-angle-degrees = DIMDIAMETER Укажите угол текста (градусы): .dimedit-enter-text-override-blank-reset-to-mea = DIMEDIT Введите текстовую оверрайд (blank = reset to measured): diff --git a/locales/tr-TR/opencadstudio.ftl b/locales/tr-TR/opencadstudio.ftl index 371bc4476..381332852 100644 --- a/locales/tr-TR/opencadstudio.ftl +++ b/locales/tr-TR/opencadstudio.ftl @@ -1835,8 +1835,8 @@ annotate = .dimcontinue-no-base-dimension-found-place-a-di = DIMCONTINUE Temel ölçü bulunamadı. Önce bir ölçü yerleştirin. .dimcontinue-specify-a-second-extension-line-or = DIMCONTINUE İkinci uzatma çizgisinin başlangıcını belirtin (çıkmak için Enter): .dimdiameter-enter-dimension-text-blank-measure = DIMDIAMETER Ölçü metnini girin (boş = ölçülen değer): - .dimdiameter-specify-center-point = DIMDIAMETER Merkez noktasını belirtin: - .dimdiameter-specify-dimension-line-location-te = DIMDIAMETER Ölçü çizgisinin konumunu belirtin [Metin/Açı]: + .dimdiameter-select-arc-circle-or-polyline-arc = DIMDIAMETER Yay, daire veya çoklu çizgi yayı seçin: + .dimdiameter-specify-dimension-line-location-text = DIMDIAMETER Ölçü çizgisinin konumunu belirtin [Çok satırlı metin/Metin/Açı]: .dimdiameter-specify-point-on-circle = DIMDIAMETER Daire üzerindeki noktayı belirtin: .dimdiameter-specify-text-angle-degrees = DIMDIAMETER Metin açısını belirtin (derece): .dimedit-enter-text-override-blank-reset-to-mea = DIMEDIT Metin geçersiz kılmasını girin (boş = ölçülen değere sıfırla): diff --git a/locales/zh-CN/opencadstudio.ftl b/locales/zh-CN/opencadstudio.ftl index e94e3930c..117a71561 100644 --- a/locales/zh-CN/opencadstudio.ftl +++ b/locales/zh-CN/opencadstudio.ftl @@ -1812,8 +1812,8 @@ annotate = .dimcontinue-no-base-dimension-found-place-a-di = DIMCONTINUE 未找到基准标注。请先放置标注。 .dimcontinue-specify-a-second-extension-line-or = DIMCONTINUE 指定第二条尺寸界线原点(按 Enter 退出): .dimdiameter-enter-dimension-text-blank-measure = DIMDIAMETER 输入标注文字(空白 = 测量值): - .dimdiameter-specify-center-point = DIMDIAMETER 指定中心点: - .dimdiameter-specify-dimension-line-location-te = DIMDIAMETER 指定尺寸线位置 [文字/角度]: + .dimdiameter-select-arc-circle-or-polyline-arc = DIMDIAMETER 选择圆弧、圆或多段线圆弧: + .dimdiameter-specify-dimension-line-location-text = DIMDIAMETER 指定尺寸线位置 [多行文字/文字/角度]: .dimdiameter-specify-point-on-circle = DIMDIAMETER 指定圆上的点: .dimdiameter-specify-text-angle-degrees = DIMDIAMETER 指定文字角度(度): .dimedit-enter-text-override-blank-reset-to-mea = DIMEDIT 输入文字替代(空白 = 重置为测量值): diff --git a/locales/zh-TW/opencadstudio.ftl b/locales/zh-TW/opencadstudio.ftl index 254e85e64..3b1f91a62 100644 --- a/locales/zh-TW/opencadstudio.ftl +++ b/locales/zh-TW/opencadstudio.ftl @@ -1824,8 +1824,8 @@ annotate = .dimcontinue-no-base-dimension-found-place-a-di = DIMCONTINUE 未找到基準標註。請先放置標註。 .dimcontinue-specify-a-second-extension-line-or = DIMCONTINUE 指定第二條尺寸界線原點(按 Enter 退出): .dimdiameter-enter-dimension-text-blank-measure = DIMDIAMETER 輸入標註文字(空白 = 測量值): - .dimdiameter-specify-center-point = DIMDIAMETER 指定中心點: - .dimdiameter-specify-dimension-line-location-te = DIMDIAMETER 指定尺寸線位置 [文字/角度]: + .dimdiameter-select-arc-circle-or-polyline-arc = DIMDIAMETER 選擇圓弧、圓或聚合線圓弧: + .dimdiameter-specify-dimension-line-location-text = DIMDIAMETER 指定尺寸線位置 [多行文字/文字/角度]: .dimdiameter-specify-point-on-circle = DIMDIAMETER 指定圓上的點: .dimdiameter-specify-text-angle-degrees = DIMDIAMETER 指定文字角度(度): .dimedit-enter-text-override-blank-reset-to-mea = DIMEDIT 輸入文字替代(空白 = 重置為測量值): diff --git a/src/entities/dimension.rs b/src/entities/dimension.rs index a3fa70034..22e7f4860 100644 --- a/src/entities/dimension.rs +++ b/src/entities/dimension.rs @@ -86,19 +86,24 @@ fn base_props(base: &DimensionBase) -> Vec Vec { - if let Dimension::Radius(radius) = dim { + let compact_radial = match dim { + Dimension::Radius(radius) => Some((&radius.base, radius.leader_length)), + Dimension::Diameter(diameter) => Some((&diameter.base, diameter.leader_length)), + _ => None, + }; + if let Some((base, leader_length)) = compact_radial { return vec![PropSection { title: t!("Misc").into_owned(), props: vec![ Property { label: t!("Dimension style").into_owned(), field: "style_name", - value: PropValue::PlainText(radius.base.style_name.clone()), + value: PropValue::PlainText(base.style_name.clone()), }, edit( t!("Leader Length").as_ref(), "leader_length", - radius.leader_length, + leader_length, ), ], }]; @@ -1313,11 +1318,29 @@ impl Grippable for Dimension { 1 => apply_to_v3(&mut d.definition_point, &apply), _ => {} }, - Dimension::Diameter(d) => match grip_id { - 0 => apply_to_v3(&mut d.angle_vertex, &apply), - 1 => apply_to_v3(&mut d.definition_point, &apply), - _ => {} - }, + Dimension::Diameter(d) => { + let center = d.center(); + let radius = d.measurement() * 0.5; + let mut target = match grip_id { + 0 => d.angle_vertex, + 1 => d.definition_point, + _ => center, + }; + if grip_id <= 1 { + apply_to_v3(&mut target, &apply); + let offset = target - center; + if offset.length_squared() > 1e-24 && radius > 1e-12 { + let radial = offset.normalize() * radius; + if grip_id == 0 { + d.angle_vertex = center + radial; + d.definition_point = center - radial; + } else { + d.definition_point = center + radial; + d.angle_vertex = center - radial; + } + } + } + } Dimension::Angular2Ln(d) => match grip_id { 0 => apply_to_v3(&mut d.first_point, &apply), 1 => apply_to_v3(&mut d.second_point, &apply), @@ -1700,9 +1723,18 @@ pub fn style_sections( inherited_name, ) } else { - arrow_name(ov::DIMBLK1, s.dimblk1, &s.dimblk1_name) + let inherited = if matches!(dimension, Dimension::Diameter(_)) && !s.dimsah { + (s.dimblk, s.dimblk_name.as_str()) + } else { + (s.dimblk1, s.dimblk1_name.as_str()) + }; + arrow_name(ov::DIMBLK1, inherited.0, inherited.1) + }; + let arrow_2 = if matches!(dimension, Dimension::Diameter(_)) && !s.dimsah { + arrow_name(ov::DIMBLK2, s.dimblk, &s.dimblk_name) + } else { + arrow_name(ov::DIMBLK2, s.dimblk2, &s.dimblk2_name) }; - let arrow_2 = arrow_name(ov::DIMBLK2, s.dimblk2, &s.dimblk2_name); for current in [&arrow_1, &arrow_2] { if !arrow_options.contains(current) { arrow_options.push(current.clone()); @@ -2379,7 +2411,7 @@ pub fn style_sections( }, ]; - if matches!(dimension, Dimension::Radius(_)) { + if matches!(dimension, Dimension::Radius(_) | Dimension::Diameter(_)) { let dimcen = real(ov::DIMCEN, s.dimcen); let center_type = if dimcen > 1e-12 { "Center marks" @@ -2406,9 +2438,30 @@ pub fn style_sections( "dim_ext_line_ext", "dim_ext_line_offset", ]; + const DIAMETER_LINE_FIELDS: &[&str] = &[ + "dim_arrowhead_1", + "dim_arrowhead_2", + "dim_arrow_size", + "dim_line_lineweight", + "dim_ext_line_lineweight", + "dim_line_1", + "dim_line_2", + "dim_line_color", + "dim_linetype", + "dim_ext_linetype_1", + "dim_ext_line_1", + "dim_ext_line_color", + "dim_ext_line_ext", + "dim_ext_line_offset", + ]; + let retained = if matches!(dimension, Dimension::Diameter(_)) { + DIAMETER_LINE_FIELDS + } else { + RADIUS_LINE_FIELDS + }; lines .props - .retain(|property| RADIUS_LINE_FIELDS.contains(&property.field)); + .retain(|property| retained.contains(&property.field)); lines.props.push(choice( t!("Center mark").as_ref(), "dim_center_type", @@ -3049,6 +3102,32 @@ fn tessellate_dimension_inner( defer_arrow_hatches, ); (arrow.clone(), arrow) + } else if matches!(dim, Dimension::Diameter(_)) { + let data = &dim.base().common.extended_data; + let first = crate::entities::dim_override::handle( + data, + crate::entities::dim_override::DIMBLK1, + ) + .unwrap_or(if dimsah { s.dimblk1 } else { s.dimblk }); + let second = crate::entities::dim_override::handle( + data, + crate::entities::dim_override::DIMBLK2, + ) + .unwrap_or(if dimsah { s.dimblk2 } else { s.dimblk }); + ( + arrow_from_block_with_deferred_hatch( + document, + first, + dimasz, + defer_arrow_hatches, + ), + arrow_from_block_with_deferred_hatch( + document, + second, + dimasz, + defer_arrow_hatches, + ), + ) } else if dimsah { ( arrow_from_block_with_deferred_hatch( @@ -3133,6 +3212,7 @@ fn tessellate_dimension_inner( dimtofl: style.map(|s| s.dimtofl).unwrap_or(false), text_position, horizontal_text, + text_movement: style.map(|s| s.dimtmove).unwrap_or(0), text_break, }, SuppressFlags { @@ -3642,7 +3722,15 @@ fn dimtmove_leader_endpoints(dim: &Dimension) -> Option<(Vec3, Vec3)> { (first + perp * off1 + second + perp * off2) * 0.5 } Dimension::Radius(_) => return None, - Dimension::Diameter(d) => (lv(d.angle_vertex) + lv(d.definition_point)) * 0.5, + Dimension::Diameter(d) => { + let chord = lv(d.angle_vertex); + let far_chord = lv(d.definition_point); + if chord.distance_squared(lv(txt)) <= far_chord.distance_squared(lv(txt)) { + chord + } else { + far_chord + } + } Dimension::Angular2Ln(d) => lv(d.dimension_arc), Dimension::Angular3Pt(d) => lv(d.definition_point), _ => return None, @@ -3716,6 +3804,7 @@ struct DimLineParams { dimtofl: bool, text_position: Vec3, horizontal_text: bool, + text_movement: i16, /// Text box (local centre, half-width, half-height) used to break the /// dimension line where the text sits on it, so a DIMTFILL background reads /// over the line. None when the text doesn't overlap the line. @@ -3833,26 +3922,20 @@ fn dimension_geometry( } } Dimension::Diameter(d) => { - // angle_vertex is the circle centre and definition_point a point on - // the circle. The diameter line runs edge-to-edge THROUGH the centre - // (far edge → near edge), with arrows pointing inward at each edge. - let center = lv(d.angle_vertex); - let edge = lv(d.definition_point); - let far = center * 2.0 - edge; - add_segment(&mut g.dim_lines, far, edge); - append_arrow(&mut g, edge, normalized_or(far - edge, Vec3::X), arrow1); - append_arrow(&mut g, far, normalized_or(edge - far, Vec3::X), arrow2); - // Diameter leader: continue past the near edge toward the text. - if d.leader_length.abs() > 1e-9 { - let text = dimension_text_position(dim); - let leader_dir = normalized_or(text - edge, edge - far); - add_segment( - &mut g.dim_lines, - edge, - edge + leader_dir * (d.leader_length as f32), - ); - } - let radius = (edge - center).length(); + let chord = lv(d.angle_vertex); + let far_chord = lv(d.definition_point); + append_diameter_dimension( + &mut g, + chord, + far_chord, + arrow1, + arrow2, + d.leader_length as f32, + params, + suppress, + ); + let center = (chord + far_chord) * 0.5; + let radius = chord.distance(far_chord) * 0.5; append_center_mark(&mut g, center, params.dimcen, radius); } Dimension::Angular2Ln(d) => { @@ -4137,6 +4220,107 @@ fn append_linear_dimension( } } +fn append_diameter_dimension( + g: &mut DimGeom, + chord: Vec3, + far_chord: Vec3, + arrow1: &ArrowKind, + arrow2: &ArrowKind, + leader_length: f32, + params: DimLineParams, + suppress: SuppressFlags, +) { + let axis = normalized_or(far_chord - chord, Vec3::X); + let diameter = chord.distance(far_chord); + if diameter <= 1e-6 { + return; + } + + let arrows_outside = if params.ticks || params.arrow_len <= 1e-6 { + false + } else if diameter < 2.0 * params.arrow_len { + true + } else if diameter < params.text_width + 2.0 * params.arrow_len { + match params.dimatfit { + 0 | 1 => true, + 2 => false, + _ => params.text_width <= diameter, + } + } else { + false + }; + + let extension = if params.ticks { params.dimdle } else { 0.0 }; + let first = chord - axis * extension; + let second = far_chord + axis * extension; + let line_length = first.distance(second); + let mut left_end = line_length * 0.5; + let mut right_start = left_end; + if let Some((text_center, half_width, half_height)) = params.text_break { + let along = (text_center - first).dot(axis); + if along > 0.0 && along < line_length { + left_end = along; + right_start = along; + let perpendicular = (text_center - (first + axis * along)).length(); + if perpendicular < half_height + && along - half_width > 0.0 + && along + half_width < line_length + { + left_end = along - half_width; + right_start = along + half_width; + } + } + } + + let draw_inside_line = !arrows_outside || params.dimtofl; + if draw_inside_line && !suppress.dim1 && left_end > 1e-6 { + add_segment(&mut g.dim_lines, first, first + axis * left_end); + } + if draw_inside_line && !suppress.dim2 && line_length - right_start > 1e-6 { + add_segment( + &mut g.dim_lines, + first + axis * right_start, + second, + ); + } + if arrows_outside && !params.dimsoxd { + let stub = params.arrow_len * 2.0; + if !suppress.dim1 { + add_segment(&mut g.dim_lines, chord - axis * stub, chord); + } + if !suppress.dim2 { + add_segment(&mut g.dim_lines, far_chord, far_chord + axis * stub); + } + } + + if arrows_outside { + append_arrow(g, chord, -axis, arrow1); + append_arrow(g, far_chord, axis, arrow2); + } else { + append_arrow(g, chord, axis, arrow1); + append_arrow(g, far_chord, -axis, arrow2); + } + + let text_along = (params.text_position - chord).dot(axis); + if params.text_movement == 0 { + let (tip, suppressed) = if params.text_position.distance_squared(chord) + <= params.text_position.distance_squared(far_chord) + { + (chord, suppress.dim1) + } else { + (far_chord, suppress.dim2) + }; + if !suppressed && leader_length.abs() > 1e-6 { + let direction = normalized_or(params.text_position - tip, axis); + add_segment(&mut g.dim_lines, tip, tip + direction * leader_length.abs()); + } else if text_along < 0.0 && !suppress.dim1 { + add_segment(&mut g.dim_lines, chord, params.text_position); + } else if text_along > diameter && !suppress.dim2 { + add_segment(&mut g.dim_lines, far_chord, params.text_position); + } + } +} + /// Draw a center mark for radius/diameter dimensions. /// DIMCEN > 0 → small "+" of half-length |DIMCEN| at the centre. /// DIMCEN < 0 → small "+" *plus* four line segments extending from the @@ -4810,6 +4994,11 @@ fn dimension_text_is_outside(dim: &Dimension, style: Option<&DimStyle>) -> bool let length = (delta.x * delta.x + delta.y * delta.y).sqrt().max(1e-12); (d.first_point, d.second_point, delta / length) } + Dimension::Diameter(d) => { + let delta = d.definition_point - d.angle_vertex; + let length = (delta.x * delta.x + delta.y * delta.y).sqrt().max(1e-12); + (d.angle_vertex, d.definition_point, delta / length) + } _ => return false, }; let first_axis = first.x * axis.x + first.y * axis.y; @@ -4856,6 +5045,8 @@ fn dimension_text_natural_rotation(dim: &Dimension) -> f64 { .unwrap_or(0.0), Dimension::Radius(d) => (d.definition_point.y - d.angle_vertex.y) .atan2(d.definition_point.x - d.angle_vertex.x), + Dimension::Diameter(d) => (d.definition_point.y - d.angle_vertex.y) + .atan2(d.definition_point.x - d.angle_vertex.x), _ => 0.0, }; // Clamp to (-π/2, π/2] so text never appears upside-down. @@ -5459,26 +5650,6 @@ fn swap_decimal_sep(s: &str, dsep_code: i16) -> String { s.replace('.', &ch.to_string()) } -fn dimension_text_position(dim: &Dimension) -> Vec3 { - let lv = |v| vec3_local(v); - let base = dim.base(); - let pos = lv(base.text_middle_point); - if pos.length_squared() > 1e-8 { - return pos; - } - match dim { - Dimension::Aligned(d) => (lv(d.first_point) + lv(d.second_point)) * 0.5, - Dimension::Linear(d) => (lv(d.first_point) + lv(d.second_point)) * 0.5, - Dimension::Radius(d) => (lv(d.angle_vertex) + lv(d.definition_point)) * 0.5, - Dimension::Diameter(d) => (lv(d.angle_vertex) + lv(d.definition_point)) * 0.5, - Dimension::Angular2Ln(d) => lv(d.dimension_arc), - Dimension::Angular3Pt(d) => lv(d.definition_point), - Dimension::Ordinate(d) => lv(d.leader_endpoint), - Dimension::Arc(d) => lv(d.definition_point), - Dimension::LargeRadial(d) => lv(d.jog_point), - } -} - fn vec3_local(v: Vector3) -> Vec3 { Vec3::new(v.x as f32, v.y as f32, v.z as f32) } @@ -5697,19 +5868,28 @@ fn dimension_text_pos_f64( } Vector3::new(x, y, d.definition_point.z) } + Dimension::Diameter(d) => { + let dx = d.definition_point.x - d.angle_vertex.x; + let dy = d.definition_point.y - d.angle_vertex.y; + let len = (dx * dx + dy * dy).sqrt().max(1e-12); + text_on_dim_line( + d.angle_vertex, + d.definition_point, + d.angle_vertex, + dx / len, + dy / len, + dimjust, + perp_off, + text_w, + arrow, + dimtix, + dimatfit, + dimtad, + ) + } _ => { - // Non-linear (radius / diameter / angular / ordinate): lift the - // natural mid point straight up by the style offset. A user-dragged - // text point is already returned by the `use_saved` gate above, so - // we must NOT short-circuit on a merely-nonzero text_middle_point - // here — that would ignore the style placement for auto-placed dims - // and make a re-style a no-op. (#181) + // Auto-placed text follows the style offset. let mid = match dim { - Dimension::Diameter(d) => Vector3::new( - (d.angle_vertex.x + d.definition_point.x) * 0.5, - (d.angle_vertex.y + d.definition_point.y) * 0.5, - (d.angle_vertex.z + d.definition_point.z) * 0.5, - ), Dimension::Angular2Ln(d) => d.dimension_arc, Dimension::Angular3Pt(d) => d.definition_point, Dimension::Ordinate(d) => d.leader_endpoint, diff --git a/src/locale_catalog.rs b/src/locale_catalog.rs index e4f7abd6a..c190e52ec 100644 --- a/src/locale_catalog.rs +++ b/src/locale_catalog.rs @@ -758,8 +758,8 @@ pub(super) fn message_attribute(source: &str) -> Option<(&'static str, &'static "DIMCONTINUE No base dimension found. Place a dimension first." => Some(("annotate", "dimcontinue-no-base-dimension-found-place-a-di")), "DIMCONTINUE Specify a second extension line origin (Enter to exit):" => Some(("annotate", "dimcontinue-specify-a-second-extension-line-or")), "DIMDIAMETER Enter dimension text (blank = measured value):" => Some(("annotate", "dimdiameter-enter-dimension-text-blank-measure")), - "DIMDIAMETER Specify center point:" => Some(("annotate", "dimdiameter-specify-center-point")), - "DIMDIAMETER Specify dimension line location [Text/Angle]:" => Some(("annotate", "dimdiameter-specify-dimension-line-location-te")), + "DIMDIAMETER Select arc, circle, or polyline arc:" => Some(("annotate", "dimdiameter-select-arc-circle-or-polyline-arc")), + "DIMDIAMETER Specify dimension line location [Mtext/Text/Angle]:" => Some(("annotate", "dimdiameter-specify-dimension-line-location-text")), "DIMDIAMETER Specify point on circle:" => Some(("annotate", "dimdiameter-specify-point-on-circle")), "DIMDIAMETER Specify text angle (degrees):" => Some(("annotate", "dimdiameter-specify-text-angle-degrees")), "DIMEDIT Enter text override (blank = reset to measured):" => Some(("annotate", "dimedit-enter-text-override-blank-reset-to-mea")), diff --git a/src/modules/annotate/diameter_dim.rs b/src/modules/annotate/diameter_dim.rs index 1fe7ccfa5..010434c71 100644 --- a/src/modules/annotate/diameter_dim.rs +++ b/src/modules/annotate/diameter_dim.rs @@ -1,11 +1,11 @@ -// DIMDIAMETER command — diameter dimension for circles and arcs. - use acadrust::entities::{Dimension, DimensionDiameter}; -use acadrust::types::Vector3; +use acadrust::types::{Handle, Vector3}; use acadrust::EntityType; use glam::{DVec3, Vec3}; -use crate::command::{CadCommand, CmdResult, WorkingPlane}; +use crate::command::{ + CadCommand, CmdOption, CmdResult, DimensionAssociationInput, WorkingPlane, +}; use crate::modules::{IconKind, ModuleEvent, ToolDef}; use crate::scene::model::wire_model::WireModel; use crate::t; @@ -22,40 +22,43 @@ pub fn tool() -> ToolDef { } enum Step { - CenterPoint, - ArcPoint(DVec3), - TextPoint { center: DVec3, arc_pt: DVec3 }, + SelectObject, + DimLine(crate::scene::dimension_assoc::RadialSourceGeometry), } pub struct DiameterDimensionCommand { step: Step, - plane: WorkingPlane, - /// Optional text that replaces the measured value (None = measurement). text_override: Option, - /// True while the next typed line is captured as the text override. awaiting_text: bool, - /// Explicit text rotation in radians (None = follow the UCS/style). text_angle: Option, - /// True while the next typed value is captured as the text angle. awaiting_angle: bool, + picked_entity: Option, + source_handle: Option, } impl DiameterDimensionCommand { pub fn new() -> Self { Self { - step: Step::CenterPoint, - plane: WorkingPlane::default(), + step: Step::SelectObject, text_override: None, awaiting_text: false, text_angle: None, awaiting_angle: false, + picked_entity: None, + source_handle: None, + } + } + + fn editor_anchor(&self) -> DVec3 { + match self.step { + Step::SelectObject => DVec3::ZERO, + Step::DimLine(source) => dvec(source.point_at_angle(source.start_angle)), } } } impl CadCommand for DiameterDimensionCommand { - fn set_working_plane(&mut self, plane: WorkingPlane) { - self.plane = plane; + fn set_working_plane(&mut self, _plane: WorkingPlane) { } fn name(&self) -> &'static str { @@ -64,54 +67,58 @@ impl CadCommand for DiameterDimensionCommand { fn prompt(&self) -> String { if self.awaiting_text { - return t!("DIMDIAMETER Enter dimension text (blank = measured value):").into_owned(); + return t!("DIMDIAMETER Enter dimension text (blank = measured value):") + .into_owned(); } if self.awaiting_angle { return t!("DIMDIAMETER Specify text angle (degrees):").into_owned(); } match self.step { - Step::CenterPoint => t!("DIMDIAMETER Specify center point:").into_owned(), - Step::ArcPoint(_) => t!("DIMDIAMETER Specify point on circle:").into_owned(), - Step::TextPoint { .. } => { - t!("DIMDIAMETER Specify dimension line location [Text/Angle]:").into_owned() + Step::SelectObject => { + t!("DIMDIAMETER Select arc, circle, or polyline arc:").into_owned() + } + Step::DimLine(_) => { + t!("DIMDIAMETER Specify dimension line location [Mtext/Text/Angle]:") + .into_owned() } } } fn on_point(&mut self, pt: DVec3) -> CmdResult { match self.step { - Step::CenterPoint => { - self.step = Step::ArcPoint(pt); - CmdResult::NeedPoint - } - Step::ArcPoint(center) => { - self.step = Step::TextPoint { center, arc_pt: pt }; - CmdResult::NeedPoint - } - Step::TextPoint { center, arc_pt } => { - let center = self.plane.to_local(center); - let arc_pt = self.plane.to_local(arc_pt); - let pt = self.plane.to_local(pt); - let mut dim = DimensionDiameter::new(v3(center), v3(arc_pt)); - dim.base.definition_point = v3(arc_pt); + Step::SelectObject => CmdResult::NeedPoint, + Step::DimLine(source) => { + let source_plane = WorkingPlane::new( + DVec3::from_array(source.plane.origin), + DVec3::from_array(source.plane.x_axis), + DVec3::from_array(source.plane.y_axis), + ); + let chord = source_plane.to_local(dvec(source.chord_at(pt.to_array()))); + let far_chord = source_plane.to_local(dvec(source.opposite_chord_at(pt.to_array()))); + let pt = source_plane.to_local(pt); + let mut dim = DimensionDiameter::new(v3(chord), v3(far_chord)); dim.base.text_middle_point = v3(pt); dim.base.insertion_point = v3(pt); - dim.leader_length = arc_pt.distance(pt); + dim.base.text_user_positioned = true; + dim.leader_length = chord.distance(pt); dim.base.actual_measurement = dim.measurement(); - dim.base.user_text = self.text_override.clone(); - // An explicit text angle overrides the default rotation. + crate::entities::dimension::set_dimension_text_override( + &mut dim.base, + self.text_override.clone(), + ); if let Some(a) = self.text_angle { dim.base.text_rotation = a; } - CmdResult::CommitAndExit(self.plane.place_entity(EntityType::Dimension( - Dimension::Diameter(dim), - ))) + CmdResult::CommitDimension { + entity: source_plane + .place_entity(EntityType::Dimension(Dimension::Diameter(dim))), + association: DimensionAssociationInput::Infer(self.source_handle), + } } } } fn on_enter(&mut self) -> CmdResult { - // A bare Enter while entering override text accepts the measured value. if self.awaiting_text { self.awaiting_text = false; return CmdResult::NeedPoint; @@ -123,24 +130,37 @@ impl CadCommand for DiameterDimensionCommand { CmdResult::Cancel } + fn on_escape(&mut self) -> CmdResult { + CmdResult::Cancel + } + fn wants_text_input(&self) -> bool { true } fn point_step_accepts_keywords(&self) -> bool { - // While entering the override text or angle it is a value, not a point step. !self.awaiting_text && !self.awaiting_angle } fn wants_text_with_spaces(&self) -> bool { - // The override text may contain spaces. self.awaiting_text } + fn options(&self) -> Vec { + if matches!(self.step, Step::DimLine(_)) && !self.awaiting_text && !self.awaiting_angle { + vec![ + CmdOption::new("MText", "MTEXT"), + CmdOption::new("Text", "TEXT"), + CmdOption::new("Angle", "ANGLE"), + ] + } else { + Vec::new() + } + } + fn on_text_input(&mut self, text: &str) -> Option { if self.awaiting_text { let t = text.trim(); - // Blank (or the "<>" placeholder) keeps the measured value. self.text_override = if t.is_empty() || t == "<>" { None } else { @@ -151,7 +171,6 @@ impl CadCommand for DiameterDimensionCommand { } if self.awaiting_angle { let t = text.trim(); - // Blank clears any explicit angle (follow the default again). self.text_angle = if t.is_empty() { None } else { @@ -160,11 +179,19 @@ impl CadCommand for DiameterDimensionCommand { self.awaiting_angle = false; return Some(CmdResult::NeedPoint); } - match text.trim().to_uppercase().as_str() { - "T" | "TEXT" | "M" | "MTEXT" => { + if !matches!(self.step, Step::DimLine(_)) { + return None; + } + match text.trim().to_ascii_uppercase().as_str() { + "T" | "TEXT" => { self.awaiting_text = true; Some(CmdResult::NeedPoint) } + "M" | "MTEXT" => Some(CmdResult::SuspendForMTextInput { + pos: self.editor_anchor(), + initial: self.text_override.clone().unwrap_or_default(), + height: 2.5, + }), "A" | "ANGLE" => { self.awaiting_angle = true; Some(CmdResult::NeedPoint) @@ -173,14 +200,60 @@ impl CadCommand for DiameterDimensionCommand { } } + fn on_editor_text(&mut self, value: String) { + let value = value.trim(); + self.text_override = if value.is_empty() || value == "<>" { + None + } else { + Some(value.to_string()) + }; + } + + fn on_editor_closed(&mut self, _committed: bool) -> CmdResult { + CmdResult::NeedPoint + } + + fn needs_entity_pick(&self) -> bool { + matches!(self.step, Step::SelectObject) + } + + fn entity_pick_highlights_hover(&self) -> bool { + true + } + + fn inject_before_entity_pick(&self) -> bool { + true + } + + fn inject_picked_entity(&mut self, entity: EntityType) { + self.picked_entity = Some(entity); + } + + fn on_entity_pick(&mut self, handle: Handle, point: DVec3) -> CmdResult { + let Some(entity) = self.picked_entity.take() else { + return CmdResult::NeedPoint; + }; + let Some(source) = crate::scene::dimension_assoc::radial_source_at( + &entity, + Vector3::new(point.x, point.y, point.z), + ) else { + return CmdResult::NeedPoint; + }; + if !source.radius.is_finite() || source.radius <= 1e-12 { + return CmdResult::NeedPoint; + } + self.source_handle = Some(handle); + self.step = Step::DimLine(source); + CmdResult::NeedPoint + } + fn on_mouse_move(&mut self, pt: DVec3) -> Option { - let pt = pt.as_vec3(); match self.step { - Step::CenterPoint => None, - Step::ArcPoint(center) => Some(preview_line(center.as_vec3(), pt)), - Step::TextPoint { center, arc_pt } => { - let far = center + (center - arc_pt); // opposite point on circle - Some(preview_line(far.as_vec3(), pt)) + Step::SelectObject => None, + Step::DimLine(source) => { + let chord = dvec(source.chord_at(pt.to_array())).as_vec3(); + let far_chord = dvec(source.opposite_chord_at(pt.to_array())).as_vec3(); + Some(preview_line(far_chord, chord, pt.as_vec3())) } } } @@ -190,7 +263,12 @@ fn v3(p: DVec3) -> Vector3 { Vector3::new(p.x, p.y, p.z) } -fn preview_line(a: Vec3, b: Vec3) -> WireModel { +fn dvec(point: Vector3) -> DVec3 { + DVec3::new(point.x, point.y, point.z) +} + +fn preview_line(far_chord: Vec3, chord: Vec3, text: Vec3) -> WireModel { + let separator = [f32::NAN; 3]; WireModel { point_marker: None, taper_widths: Vec::new(), @@ -204,11 +282,17 @@ fn preview_line(a: Vec3, b: Vec3) -> WireModel { render_instance: None, pick_tris: Vec::new(), pick_tris_low: Vec::new(), - dash_from_start: false, - dash_align_end: None, - text_verts: Vec::new(), + dash_from_start: false, + dash_align_end: None, + text_verts: Vec::new(), name: "dimdia_preview".into(), - points: vec![[a.x, a.y, a.z], [b.x, b.y, b.z]], + points: vec![ + far_chord.to_array(), + chord.to_array(), + separator, + chord.to_array(), + text.to_array(), + ], points_low: Vec::new(), color: WireModel::CYAN, selected: false, @@ -226,6 +310,4 @@ fn preview_line(a: Vec3, b: Vec3) -> WireModel { } } - -// ── Autocomplete registry ───────────────────────────────── -inventory::submit!(crate::command::CommandRegistration { names: &["DIMDIAMETER"] }); // DiameterDimensionCommand +inventory::submit!(crate::command::CommandRegistration { names: &["DIMDIAMETER"] }); diff --git a/src/modules/draw/modify/explode.rs b/src/modules/draw/modify/explode.rs index 302033f9e..c3702e0ff 100644 --- a/src/modules/draw/modify/explode.rs +++ b/src/modules/draw/modify/explode.rs @@ -612,10 +612,66 @@ struct DimMetrics { /// suppression), DIMCLRD/E/T (colours) and DIMLWD/E (lineweights). fn dim_metrics(dim: &Dimension, doc: &CadDocument) -> DimMetrics { let name = dim.base().style_name.as_str(); - let style = doc.dim_styles.iter().find(|s| { + let mut effective_style = doc.dim_styles.iter().find(|s| { s.name.eq_ignore_ascii_case(name) || (name.trim().is_empty() && s.name.eq_ignore_ascii_case("Standard")) - }); + }).cloned(); + if let Some(style) = &mut effective_style { + use crate::entities::dim_override as ov; + let data = &dim.base().common.extended_data; + macro_rules! real { + ($field:ident, $code:ident) => { + if let Some(value) = ov::real(data, ov::$code) { + style.$field = value; + } + }; + } + macro_rules! int { + ($field:ident, $code:ident) => { + if let Some(value) = ov::int(data, ov::$code) { + style.$field = value; + } + }; + } + macro_rules! flag { + ($field:ident, $code:ident) => { + if let Some(value) = ov::int(data, ov::$code) { + style.$field = value != 0; + } + }; + } + macro_rules! handle { + ($field:ident, $code:ident) => { + if let Some(value) = ov::handle(data, ov::$code) { + style.$field = value; + } + }; + } + real!(dimscale, DIMSCALE); + real!(dimasz, DIMASZ); + real!(dimcen, DIMCEN); + real!(dimexo, DIMEXO); + real!(dimexe, DIMEXE); + real!(dimtsz, DIMTSZ); + real!(dimdle, DIMDLE); + real!(dimfxl, DIMFXL); + flag!(dimfxlon, DIMFXLON); + flag!(dimse1, DIMSE1); + flag!(dimse2, DIMSE2); + flag!(dimsd1, DIMSD1); + flag!(dimsd2, DIMSD2); + flag!(dimsoxd, DIMSOXD); + flag!(dimsah, DIMSAH); + int!(dimclrd, DIMCLRD); + int!(dimclre, DIMCLRE); + int!(dimclrt, DIMCLRT); + int!(dimlwd, DIMLWD); + int!(dimlwe, DIMLWE); + handle!(dimblk, DIMBLK); + handle!(dimblk1, DIMBLK1); + handle!(dimblk2, DIMBLK2); + } + let style = effective_style.as_ref(); let scale = style .map(|s| if s.dimscale > 1e-6 { s.dimscale } else { 1.0 }) .unwrap_or(1.0); @@ -630,7 +686,15 @@ fn dim_metrics(dim: &Dimension, doc: &CadDocument) -> DimMetrics { let t = ArrowKind::Tick { size: dimtsz as f32 }; (t.clone(), t) } else if let Some(s) = style { - if s.dimsah { + if matches!(dim, Dimension::Diameter(_)) { + use crate::entities::dim_override as ov; + let data = &dim.base().common.extended_data; + let first = ov::handle(data, ov::DIMBLK1) + .unwrap_or(if s.dimsah { s.dimblk1 } else { s.dimblk }); + let second = ov::handle(data, ov::DIMBLK2) + .unwrap_or(if s.dimsah { s.dimblk2 } else { s.dimblk }); + (arrow_from_block(doc, first, asz), arrow_from_block(doc, second, asz)) + } else if s.dimsah { (arrow_from_block(doc, s.dimblk1, asz), arrow_from_block(doc, s.dimblk2, asz)) } else { let a = arrow_from_block(doc, s.dimblk, asz); @@ -993,27 +1057,101 @@ fn explode_dimension(dim: &Dimension, doc: &CadDocument) -> Vec { result.extend(dim_center_mark(center, met.dimcen, len, &dim_c)); } Dimension::Diameter(d) => { - // Full diameter through the centre (far edge -> near edge), inward - // terminators at both edges, plus the centre mark. - let (center, edge) = (d.angle_vertex, d.definition_point); - let far = v3(2.0 * center.x - edge.x, 2.0 * center.y - edge.y, edge.z); - result.push(make_seg(&far, &edge, &dim_c)); + let (edge, far) = (d.angle_vertex, d.definition_point); + let center = v3( + (edge.x + far.x) * 0.5, + (edge.y + far.y) * 0.5, + (edge.z + far.z) * 0.5, + ); let len = ((edge.x - far.x).powi(2) + (edge.y - far.y).powi(2)) .sqrt() .max(1e-12); let (ux, uy) = ((edge.x - far.x) / len, (edge.y - far.y) / len); - result.extend(dim_terminator(edge, -ux, -uy, &met.arrow1, &dim_c)); - result.extend(dim_terminator(far, ux, uy, &met.arrow2, &dim_c)); - // Optional leader past the near edge toward the text. DIM-DIA-LEADER. - if d.leader_length.abs() > 1e-9 { - let anchor = dim_text_anchor(base, center, edge); - let ld = norm2(anchor.x - edge.x, anchor.y - edge.y, ux, uy); + let ticks = met.dimtsz > 1e-9; + let extension = if ticks { met.dimdle } else { 0.0 }; + let edge_outer = v3( + edge.x + ux * extension, + edge.y + uy * extension, + edge.z, + ); + let far_outer = v3( + far.x - ux * extension, + far.y - uy * extension, + far.z, + ); + if !met.dimsd1 { + result.push(make_seg(&edge_outer, ¢er, &dim_c)); + } + if !met.dimsd2 { + result.push(make_seg(¢er, &far_outer, &dim_c)); + } + let outside = !ticks && met.dimasz > 1e-6 && len < 2.0 * met.dimasz; + if outside { + result.extend(dim_terminator(edge, ux, uy, &met.arrow1, &dim_c)); + result.extend(dim_terminator(far, -ux, -uy, &met.arrow2, &dim_c)); + if !met.dimsoxd { + let stub = 2.0 * met.dimasz; + if !met.dimsd1 { + result.push(make_seg( + &edge, + &v3(edge.x + ux * stub, edge.y + uy * stub, edge.z), + &dim_c, + )); + } + if !met.dimsd2 { + result.push(make_seg( + &far, + &v3(far.x - ux * stub, far.y - uy * stub, far.z), + &dim_c, + )); + } + } + } else { + result.extend(dim_terminator(edge, -ux, -uy, &met.arrow1, &dim_c)); + result.extend(dim_terminator(far, ux, uy, &met.arrow2, &dim_c)); + } + let anchor = dim_text_anchor(base, center, edge); + let distance_squared = |first: Vector3, second: Vector3| { + (first.x - second.x).powi(2) + + (first.y - second.y).powi(2) + + (first.z - second.z).powi(2) + }; + let (leader_tip, suppressed, fallback) = if distance_squared(anchor, edge) + <= distance_squared(anchor, far) + { + (edge, met.dimsd1, (ux, uy)) + } else { + (far, met.dimsd2, (-ux, -uy)) + }; + if !suppressed && d.leader_length.abs() > 1e-9 { + let ld = norm2( + anchor.x - leader_tip.x, + anchor.y - leader_tip.y, + fallback.0, + fallback.1, + ); result.push(make_seg( - &edge, - &v3(edge.x + ld.0 * d.leader_length, edge.y + ld.1 * d.leader_length, edge.z), + &leader_tip, + &v3( + leader_tip.x + ld.0 * d.leader_length.abs(), + leader_tip.y + ld.1 * d.leader_length.abs(), + leader_tip.z, + ), &dim_c, )); } + if !met.dimse1 { + if let Some(points) = crate::scene::dimension_assoc::radial_extension_points( + doc, + base.common.handle, + met.dimexo, + met.dimexe, + ) { + for pair in points.windows(2) { + result.push(make_seg(&pair[0], &pair[1], &ext_c)); + } + } + } result.extend(dim_center_mark(center, met.dimcen, len * 0.5, &dim_c)); } Dimension::Angular2Ln(d) => { @@ -1566,16 +1704,15 @@ mod tests { assert!(lines > 5, "angular bake must include arc chords, got {lines} lines"); } - // A diameter dimension bakes a line edge-to-edge THROUGH the centre, not a - // radius-length line. The two extreme endpoints must be equidistant from the - // centre (angle_vertex) and the centre must lie between them. + // Diameter endpoints stay equidistant from the circle center. #[test] fn diameter_dim_bakes_through_center() { use acadrust::entities::DimensionDiameter; let mut doc = CadDocument::new(); let center = Vector3::new(3.0, 4.0, 0.0); let edge = Vector3::new(8.0, 4.0, 0.0); // radius 5 along +x - let mut d = DimensionDiameter::new(center, edge); + let far = Vector3::new(-2.0, 4.0, 0.0); + let mut d = DimensionDiameter::new(edge, far); d.base.text_middle_point = Vector3::new(3.0, 9.0, 0.0); let handle = doc .add_entity(EntityType::Dimension(Dimension::Diameter(d))) diff --git a/src/scene/dimension_assoc.rs b/src/scene/dimension_assoc.rs index a96423974..ccc3fb9ac 100644 --- a/src/scene/dimension_assoc.rs +++ b/src/scene/dimension_assoc.rs @@ -48,6 +48,10 @@ impl RadialSourceGeometry { self.point_at_angle(self.angle_at(point)) } + pub(crate) fn opposite_chord_at(self, point: DPoint) -> Vector3 { + self.point_at_angle(self.angle_at(point) + std::f64::consts::PI) + } + fn contains_angle(self, angle: f64) -> bool { !self.limited || angle_within_arc(angle, self.start_angle, self.end_angle) } @@ -448,11 +452,14 @@ pub(crate) fn radial_extension_points( gap: f64, extension: f64, ) -> Option> { - let EntityType::Dimension(Dimension::Radius(radius_dimension)) = - document.get_entity(dimension)? - else { + let EntityType::Dimension(dimension_entity) = document.get_entity(dimension)? else { return None; }; + let target_point = match dimension_entity { + Dimension::Radius(radius) => radius.definition_point, + Dimension::Diameter(diameter) => diameter.angle_vertex, + _ => return None, + }; let association = document.objects.values().find_map(|object| { let ObjectType::Associative(object) = object else { return None; @@ -468,7 +475,7 @@ pub(crate) fn radial_extension_points( if !radial.limited || radial.radius <= 1e-12 { return None; } - let target = radial.angle_at(dpoint(radius_dimension.definition_point)); + let target = radial.angle_at(dpoint(target_point)); if radial.contains_angle(target) { return None; } @@ -536,32 +543,37 @@ impl Scene { else { return; }; - if let Dimension::Radius(radius_dimension) = dimension_entity { + let radial_data = match dimension_entity { + Dimension::Radius(radius) => Some(( + radius.angle_vertex, + radius.measurement(), + radius.definition_point, + )), + Dimension::Diameter(diameter) => Some(( + diameter.center(), + diameter.measurement() * 0.5, + diameter.angle_vertex, + )), + _ => None, + }; + if let Some((center, measured_radius, chord)) = radial_data { let Some(source) = sources.iter().flatten().next().copied() else { return; }; let Some(source_entity) = self.document.get_entity(source.handle) else { return; }; - let measured_radius = radius_dimension.measurement(); let radial = source .marker .and_then(|marker| radial_source_for_marker(source_entity, marker)) - .or_else(|| { - radial_source_matching( - source_entity, - radius_dimension.angle_vertex, - measured_radius, - radius_dimension.definition_point, - ) - }); + .or_else(|| radial_source_matching(source_entity, center, measured_radius, chord)); let Some(radial) = radial else { return; }; let angle = if source.marker.is_some() && source.parameter.is_finite() { source.parameter } else { - radial.angle_at(dpoint(radius_dimension.definition_point)) + radial.angle_at(dpoint(chord)) }; let reference = AssocDimensionReference { class_name: "AcDbOsnapPointRef".to_string(), @@ -570,7 +582,7 @@ impl Scene { main_subent_type: 1, main_gs_marker: radial.marker, osnap_distance: angle, - osnap_point: radius_dimension.definition_point, + osnap_point: chord, ..AssocDimensionReference::default() }; self.store_dimension_association( @@ -686,8 +698,21 @@ impl Scene { else { return [None, None]; }; - if let Dimension::Radius(radius) = entity { - let measurement = radius.measurement(); + let radial_data = match entity { + Dimension::Radius(radius) => Some(( + radius.angle_vertex, + radius.measurement(), + radius.definition_point, + )), + Dimension::Diameter(diameter) => Some(( + diameter.center(), + diameter.measurement() * 0.5, + diameter.angle_vertex, + )), + _ => None, + }; + if let Some((center, radius, chord)) = radial_data { + let tolerance = radius.abs().max(1.0) * 1e-9; let source = self .document .entities() @@ -695,16 +720,12 @@ impl Scene { .filter_map(|candidate| { let radial = radial_source_matching( candidate, - radius.angle_vertex, - measurement, - radius.definition_point, + center, + radius, + chord, )?; - let center_error = point_distance_squared( - radial.center_world(), - radius.angle_vertex, - ); - let radius_error = (radial.radius - measurement).powi(2); - let tolerance = measurement.abs().max(1.0) * 1e-9; + let center_error = point_distance_squared(radial.center_world(), center); + let radius_error = (radial.radius - radius).powi(2); (center_error + radius_error <= tolerance * tolerance).then_some(( center_error + radius_error, candidate.common().handle, @@ -848,6 +869,27 @@ impl Scene { } radius.base.actual_measurement = radius.measurement(); } + Dimension::Diameter(diameter) => { + let Some((radial, angle)) = radial_source else { + continue; + }; + let old_chord = diameter.angle_vertex; + let new_chord = radial.point_at_angle(angle); + let new_far_chord = radial.point_at_angle(angle + std::f64::consts::PI); + let delta = Vector3::new( + new_chord.x - old_chord.x, + new_chord.y - old_chord.y, + new_chord.z - old_chord.z, + ); + diameter.angle_vertex = new_chord; + diameter.definition_point = new_far_chord; + diameter.base.definition_point = new_far_chord; + if diameter.base.text_user_positioned { + diameter.base.text_middle_point = diameter.base.text_middle_point + delta; + diameter.base.insertion_point = diameter.base.insertion_point + delta; + } + diameter.base.actual_measurement = diameter.measurement(); + } _ => continue, } dimension.base_mut().actual_measurement = dimension.measurement();