diff --git a/Cargo.lock b/Cargo.lock index 11779fe0..cbd9f3b6 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=0f746f7#0f746f78ca871fded0e910b758d787eb9d4e74f8" +source = "git+https://git@github.com/HakanSeven12/cadcodec.git?rev=2aa1181#2aa1181776b7c1848efe58e3d41ed35138ed7455" dependencies = [ "ahash 0.8.12", "anyhow", diff --git a/Cargo.toml b/Cargo.toml index 9e1bb939..7a0b74ac 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 = "0f746f7", features = ["serde"] } +acadrust = { git = "https://github.com/HakanSeven12/cadcodec.git", rev = "2aa1181", 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 = "0f746f7" } +acadrust = { git = "https://git@github.com/HakanSeven12/cadcodec.git", rev = "2aa1181" } [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 3660ca43..21ff57e8 100644 --- a/locales/ar-SA/opencadstudio.ftl +++ b/locales/ar-SA/opencadstudio.ftl @@ -1854,7 +1854,9 @@ annotate = .dimlinear-specify-second-extension-line-origin = DIMLINEAR حدد أصل خط الامتداد الثاني [نص/زاوية]: .dimlinear-specify-text-angle-degrees = DIMLINEAR حدد زاوية النص (بالدرجات): .dimordinate-specify-feature-location = DIMORDINATE حدد موقع المعلم: - .dimordinate-specify-leader-endpoint = DIMORDINATE حدد نقطة نهاية الخط القائد: + .dimordinate-enter-dimension-text-blank-measured = DIMORDINATE أدخل نص البُعد (فارغ = القيمة المقاسة): + .dimordinate-specify-leader-endpoint = DIMORDINATE حدد نقطة نهاية الخط القائد [Xdatum/Ydatum/Mtext/Text/Angle]: + .dimordinate-specify-text-angle-degrees = DIMORDINATE حدد زاوية النص (بالدرجات): .dimradius-enter-dimension-text-blank-measured = DIMRADIUS أدخل نص البُعد (فارغ = القيمة المقاسة): .dimradius-select-arc-circle-or-polyline-arc = DIMRADIUS حدد قوسًا أو دائرة أو قوسًا متعدد الخطوط: .dimradius-specify-dimension-line-location-text = DIMRADIUS حدد موقع خط البُعد [نص متعدد الأسطر/نص/زاوية]: diff --git a/locales/bg-BG/opencadstudio.ftl b/locales/bg-BG/opencadstudio.ftl index d26b612b..d4005dbc 100644 --- a/locales/bg-BG/opencadstudio.ftl +++ b/locales/bg-BG/opencadstudio.ftl @@ -1841,7 +1841,9 @@ annotate = .dimlinear-specify-second-extension-line-origin = DIMLINEAR Посочи начало на втората удължителна линия [Текст/Ъгъл]: .dimlinear-specify-text-angle-degrees = DIMLINEAR Посочи ъгъл на текста (градуси): .dimordinate-specify-feature-location = DIMORDINATE Посочи местоположение на елемента: - .dimordinate-specify-leader-endpoint = DIMORDINATE Посочи крайна точка на водача: + .dimordinate-enter-dimension-text-blank-measured = DIMORDINATE Въведи текст на оразмеряване (празно = измерена стойност): + .dimordinate-specify-leader-endpoint = DIMORDINATE Посочи крайна точка на водача [Xdatum/Ydatum/Mtext/Text/Angle]: + .dimordinate-specify-text-angle-degrees = DIMORDINATE Посочи ъгъл на текста (градуси): .dimradius-enter-dimension-text-blank-measured = DIMRADIUS Въведи текст на оразмеряване (празно = измерена стойност): .dimradius-select-arc-circle-or-polyline-arc = DIMRADIUS Избери дъга, окръжност или дъгов сегмент на полилиния: .dimradius-specify-dimension-line-location-text = DIMRADIUS Посочи местоположение на линията за оразмеряване [Мтекст/Текст/Ъгъл]: diff --git a/locales/cs-CZ/opencadstudio.ftl b/locales/cs-CZ/opencadstudio.ftl index 1db1ceb6..92cf2e7d 100644 --- a/locales/cs-CZ/opencadstudio.ftl +++ b/locales/cs-CZ/opencadstudio.ftl @@ -1841,7 +1841,9 @@ annotate = .dimlinear-specify-second-extension-line-origin = DIMLINEAR Zadejte počátek druhé vynášecí čáry [Text/Úhel]: .dimlinear-specify-text-angle-degrees = DIMLINEAR Zadejte úhel textu (stupně): .dimordinate-specify-feature-location = DIMORDINATE Zadejte umístění funkce: - .dimordinate-specify-leader-endpoint = DIMORDINATE Zadejte koncový bod odkazu: + .dimordinate-enter-dimension-text-blank-measured = DIMORDINATE Zadejte text rozměru (prázdné = naměřená hodnota): + .dimordinate-specify-leader-endpoint = DIMORDINATE Zadejte koncový bod odkazu [Xdatum/Ydatum/Mtext/Text/Angle]: + .dimordinate-specify-text-angle-degrees = DIMORDINATE Zadejte úhel textu (stupně): .dimradius-enter-dimension-text-blank-measured = Text rozměru DIMRADIUS Enter (prázdná naměřená hodnota =): .dimradius-select-arc-circle-or-polyline-arc = DIMRADIUS Vyberte oblouk, kružnici nebo obloukový segment křivky: .dimradius-specify-dimension-line-location-text = DIMRADIUS Určete umístění kótovací čáry [MText/Text/Úhel]: diff --git a/locales/de-DE/opencadstudio.ftl b/locales/de-DE/opencadstudio.ftl index 151aec50..e71535fe 100644 --- a/locales/de-DE/opencadstudio.ftl +++ b/locales/de-DE/opencadstudio.ftl @@ -1842,7 +1842,9 @@ annotate = .dimlinear-specify-second-extension-line-origin = DIMLINEAR Geben Sie den Ursprung der zweiten Erweiterungslinie an [Text/Winkel]: .dimlinear-specify-text-angle-degrees = DIMLINEAR Textwinkel angeben (Grad): .dimordinate-specify-feature-location = DIMORDINATE Bezugspunkt angeben: - .dimordinate-specify-leader-endpoint = DIMORDINATE Endpunkt der Führungslinie angeben: + .dimordinate-enter-dimension-text-blank-measured = DIMORDINATE Bemaßungstext eingeben (leer = Messwert): + .dimordinate-specify-leader-endpoint = DIMORDINATE Endpunkt der Führungslinie angeben [Xdatum/Ydatum/Mtext/Text/Angle]: + .dimordinate-specify-text-angle-degrees = DIMORDINATE Textwinkel angeben (Grad): .dimradius-enter-dimension-text-blank-measured = DIMRADIUS Bemaßungstext eingeben (leer = Messwert): .dimradius-select-arc-circle-or-polyline-arc = DIMRADIUS Bogen, Kreis oder Polylinienbogen auswählen: .dimradius-specify-dimension-line-location-text = DIMRADIUS Lage der Dimensionslinie angeben [MText/Text/Winkel]: diff --git a/locales/en-US/opencadstudio.ftl b/locales/en-US/opencadstudio.ftl index 90ddec99..27566f98 100644 --- a/locales/en-US/opencadstudio.ftl +++ b/locales/en-US/opencadstudio.ftl @@ -1872,7 +1872,9 @@ annotate = .dimlinear-specify-second-extension-line-origin = DIMLINEAR Specify second extension line origin [Text/Angle]: .dimlinear-specify-text-angle-degrees = DIMLINEAR Specify text angle (degrees): .dimordinate-specify-feature-location = DIMORDINATE Specify feature location: - .dimordinate-specify-leader-endpoint = DIMORDINATE Specify leader endpoint: + .dimordinate-enter-dimension-text-blank-measured = DIMORDINATE Enter dimension text (blank = measured value): + .dimordinate-specify-leader-endpoint = DIMORDINATE Specify leader endpoint [Xdatum/Ydatum/Mtext/Text/Angle]: + .dimordinate-specify-text-angle-degrees = DIMORDINATE Specify text angle (degrees): .dimradius-enter-dimension-text-blank-measured = DIMRADIUS Enter dimension text (blank = measured value): .dimradius-select-arc-circle-or-polyline-arc = DIMRADIUS Select arc, circle, or polyline arc: .dimradius-specify-dimension-line-location-text = DIMRADIUS Specify dimension line location [Mtext/Text/Angle]: diff --git a/locales/es-ES/opencadstudio.ftl b/locales/es-ES/opencadstudio.ftl index 3cbb886a..e158ab8f 100644 --- a/locales/es-ES/opencadstudio.ftl +++ b/locales/es-ES/opencadstudio.ftl @@ -1842,7 +1842,9 @@ annotate = .dimlinear-specify-second-extension-line-origin = DIMLINEAR Especifique el origen de la segunda línea de referencia [Texto/Ángulo]: .dimlinear-specify-text-angle-degrees = DIMLINEAR Especifique el ángulo del texto (grados): .dimordinate-specify-feature-location = DIMORDINATE Especifique la ubicación del elemento: - .dimordinate-specify-leader-endpoint = DIMORDINATE Especifique el punto final de la directriz: + .dimordinate-enter-dimension-text-blank-measured = DIMORDINATE Introduzca el texto de cota (vacío = valor medido): + .dimordinate-specify-leader-endpoint = DIMORDINATE Especifique el punto final de la directriz [Xdatum/Ydatum/Mtext/Text/Angle]: + .dimordinate-specify-text-angle-degrees = DIMORDINATE Especifique el ángulo del texto (grados): .dimradius-enter-dimension-text-blank-measured = DIMRADIUS Introduzca el texto de cota (vacío = valor medido): .dimradius-select-arc-circle-or-polyline-arc = DIMRADIUS Seleccione un arco, círculo o arco de polilínea: .dimradius-specify-dimension-line-location-text = DIMRADIUS Especifique la ubicación de la línea de cota [Mtexto/Texto/Ángulo]: diff --git a/locales/fi-FI/opencadstudio.ftl b/locales/fi-FI/opencadstudio.ftl index 7eeb3327..7308d1b8 100644 --- a/locales/fi-FI/opencadstudio.ftl +++ b/locales/fi-FI/opencadstudio.ftl @@ -1841,7 +1841,9 @@ annotate = .dimlinear-specify-second-extension-line-origin = DIMLINEAR Määritä toisen jatkolinjan alkuperä [teksti/kulma]: .dimlinear-specify-text-angle-degrees = DIMLINEAR Määritä tekstin kulma (asteita): .dimordinate-specify-feature-location = DIMORDINATE Määritä ominaisuuden sijainti: - .dimordinate-specify-leader-endpoint = DIMORDINATE Määritä johtajan päätepiste: + .dimordinate-enter-dimension-text-blank-measured = DIMORDINATE Syötä mittateksti (tyhjä = mitattu arvo): + .dimordinate-specify-leader-endpoint = DIMORDINATE Määritä johtajan päätepiste [Xdatum/Ydatum/Mtext/Text/Angle]: + .dimordinate-specify-text-angle-degrees = DIMORDINATE Määritä tekstin kulma (asteita): .dimradius-enter-dimension-text-blank-measured = DIMRADIUS Enter mittateksti (tyhjä = mitattu arvo): .dimradius-select-arc-circle-or-polyline-arc = DIMRADIUS Valitse kaari, ympyrä tai murtoviivan kaari: .dimradius-specify-dimension-line-location-text = DIMRADIUS Määritä mittaviivan sijainti [Mteksti/teksti/kulma]: diff --git a/locales/fr-FR/opencadstudio.ftl b/locales/fr-FR/opencadstudio.ftl index 389a696e..00182b36 100644 --- a/locales/fr-FR/opencadstudio.ftl +++ b/locales/fr-FR/opencadstudio.ftl @@ -1842,7 +1842,9 @@ annotate = .dimlinear-specify-second-extension-line-origin = DIMLINEAR Spécifiez l'origine de la deuxième ligne d'extension [Texte/Angle]: .dimlinear-specify-text-angle-degrees = DIMLINEAR Spécifiez l'angle de texte (degrés): .dimordinate-specify-feature-location = DIMORDINATE Spécifiez le point à coter : - .dimordinate-specify-leader-endpoint = DIMORDINATE Spécifiez l’extrémité du repère : + .dimordinate-enter-dimension-text-blank-measured = DIMORDINATE Entrez le texte de cote (vide = valeur mesurée) : + .dimordinate-specify-leader-endpoint = DIMORDINATE Spécifiez l’extrémité du repère [Xdatum/Ydatum/Mtext/Text/Angle] : + .dimordinate-specify-text-angle-degrees = DIMORDINATE Spécifiez l'angle du texte (degrés) : .dimradius-enter-dimension-text-blank-measured = DIMRADIUS Entrer le texte dimensionnel (blanc = valeur mesurée): .dimradius-select-arc-circle-or-polyline-arc = DIMRADIUS Sélectionnez un arc, un cercle ou un arc de polyligne : .dimradius-specify-dimension-line-location-text = DIMRADIUS Spécifiez la position de la ligne de cote [Mtexte/Texte/Angle] : diff --git a/locales/hi-IN/opencadstudio.ftl b/locales/hi-IN/opencadstudio.ftl index d4242268..30acc142 100644 --- a/locales/hi-IN/opencadstudio.ftl +++ b/locales/hi-IN/opencadstudio.ftl @@ -1830,7 +1830,9 @@ annotate = .dimlinear-specify-second-extension-line-origin = DIMLINEAR दूसरी एक्सटेंशन लाइन उत्पत्ति निर्दिष्ट करें [टेक्स्ट / एंगल]: .dimlinear-specify-text-angle-degrees = DIMLINEAR पाठ कोण निर्दिष्ट करें (डिग्री): .dimordinate-specify-feature-location = DIMORDINATE सुविधा स्थान निर्दिष्ट करें: - .dimordinate-specify-leader-endpoint = DIMORDINATE लीडर समापन बिंदु निर्दिष्ट करें: + .dimordinate-enter-dimension-text-blank-measured = DIMORDINATE आयाम टेक्स्ट दर्ज करें (रिक्त = मापा मान): + .dimordinate-specify-leader-endpoint = DIMORDINATE लीडर समापन बिंदु निर्दिष्ट करें [Xdatum/Ydatum/Mtext/Text/Angle]: + .dimordinate-specify-text-angle-degrees = DIMORDINATE पाठ कोण निर्दिष्ट करें (डिग्री): .dimradius-enter-dimension-text-blank-measured = DIMRADIUS आयाम टेक्स्ट दर्ज करें (blank = मापा मान): .dimradius-select-arc-circle-or-polyline-arc = DIMRADIUS आर्क, सर्कल या पॉलीलाइन आर्क चुनें: .dimradius-specify-dimension-line-location-text = DIMRADIUS आयाम लाइन स्थान निर्दिष्ट करें [एमटेक्स्ट/टेक्स्ट/एंगल]: diff --git a/locales/hu-HU/opencadstudio.ftl b/locales/hu-HU/opencadstudio.ftl index 6aa9ef22..cbcf8e15 100644 --- a/locales/hu-HU/opencadstudio.ftl +++ b/locales/hu-HU/opencadstudio.ftl @@ -1841,7 +1841,9 @@ annotate = .dimlinear-specify-second-extension-line-origin = DIMLINEAR Adja meg a második mellékvonal eredetét [szöveg/szög]: .dimlinear-specify-text-angle-degrees = DIMLINEAR Adja meg a szöveg szögét (fokban): .dimordinate-specify-feature-location = DIMORDINATE Jellemző helyének megadása: - .dimordinate-specify-leader-endpoint = DIMORDINATE Vezető végpont megadása: + .dimordinate-enter-dimension-text-blank-measured = DIMORDINATE Adja meg a méretszöveget (üres = mért érték): + .dimordinate-specify-leader-endpoint = DIMORDINATE Vezető végpont megadása [Xdatum/Ydatum/Mtext/Text/Angle]: + .dimordinate-specify-text-angle-degrees = DIMORDINATE Adja meg a szöveg szögét (fokban): .dimradius-enter-dimension-text-blank-measured = DIMRADIUS Enter méretszöveg (üres = mért érték): .dimradius-select-arc-circle-or-polyline-arc = DIMRADIUS Válasszon ívet, kört vagy vonalláncívet: .dimradius-specify-dimension-line-location-text = DIMRADIUS A méretvonal helyének megadása [Mszöveg/szöveg/szög]: diff --git a/locales/it-IT/opencadstudio.ftl b/locales/it-IT/opencadstudio.ftl index 38b76b02..839d8fcb 100644 --- a/locales/it-IT/opencadstudio.ftl +++ b/locales/it-IT/opencadstudio.ftl @@ -1841,7 +1841,9 @@ annotate = .dimlinear-specify-second-extension-line-origin = DIMLINEAR Specificare l'origine della seconda linea di estensione [Testo/Angolo]: .dimlinear-specify-text-angle-degrees = DIMLINEAR Specificare l'angolo del testo (gradi): .dimordinate-specify-feature-location = DIMORDINATE Specificare la posizione dell'elemento: - .dimordinate-specify-leader-endpoint = DIMORDINATE Specificare il punto finale della guida: + .dimordinate-enter-dimension-text-blank-measured = DIMORDINATE Immettere il testo della quota (vuoto = valore misurato): + .dimordinate-specify-leader-endpoint = DIMORDINATE Specificare il punto finale della guida [Xdatum/Ydatum/Mtext/Text/Angle]: + .dimordinate-specify-text-angle-degrees = DIMORDINATE Specificare l'angolo del testo (gradi): .dimradius-enter-dimension-text-blank-measured = Testo della dimensione DIMRADIUS Enter (valore misurato = vuoto): .dimradius-select-arc-circle-or-polyline-arc = DIMRADIUS Selezionare un arco, un cerchio o un arco di polilinea: .dimradius-specify-dimension-line-location-text = DIMRADIUS Specificare la posizione della linea di quota [Mtesto/Testo/Angolo]: diff --git a/locales/ja-JP/opencadstudio.ftl b/locales/ja-JP/opencadstudio.ftl index 0f95f1f1..90fb13d8 100644 --- a/locales/ja-JP/opencadstudio.ftl +++ b/locales/ja-JP/opencadstudio.ftl @@ -1832,7 +1832,9 @@ annotate = .dimlinear-specify-second-extension-line-origin = DIMLINEAR 2 本目の寸法補助線の起点を指定 [文字/角度]: .dimlinear-specify-text-angle-degrees = DIMLINEAR 文字角度を指定(度): .dimordinate-specify-feature-location = DIMORDINATE フィーチャ位置を指定: - .dimordinate-specify-leader-endpoint = DIMORDINATE 引出線の終点を指定: + .dimordinate-enter-dimension-text-blank-measured = DIMORDINATE 寸法値を入力(空白 = 計測値): + .dimordinate-specify-leader-endpoint = DIMORDINATE 引出線の終点を指定 [Xdatum/Ydatum/Mtext/Text/Angle]: + .dimordinate-specify-text-angle-degrees = DIMORDINATE 文字角度を指定(度): .dimradius-enter-dimension-text-blank-measured = DIMRADIUS 寸法値を入力(空白 = 計測値): .dimradius-select-arc-circle-or-polyline-arc = DIMRADIUS 円弧、円、またはポリライン円弧を選択: .dimradius-specify-dimension-line-location-text = DIMRADIUS 寸法線の位置を指定 [マルチテキスト/文字/角度]: diff --git a/locales/ko-KR/opencadstudio.ftl b/locales/ko-KR/opencadstudio.ftl index 5e72174f..c773bb94 100644 --- a/locales/ko-KR/opencadstudio.ftl +++ b/locales/ko-KR/opencadstudio.ftl @@ -1841,7 +1841,9 @@ annotate = .dimlinear-specify-second-extension-line-origin = DIMLINEAR 두 번째 연장선 원점 지정 [문자/각도]: .dimlinear-specify-text-angle-degrees = DIMLINEAR 텍스트 각도(도) 지정: .dimordinate-specify-feature-location = DIMORDINATE 기능 위치 지정: - .dimordinate-specify-leader-endpoint = DIMORDINATE 리더 끝점 지정: + .dimordinate-enter-dimension-text-blank-measured = DIMORDINATE 치수 문자 입력(빈 값 = 측정 값): + .dimordinate-specify-leader-endpoint = DIMORDINATE 리더 끝점 지정 [Xdatum/Ydatum/Mtext/Text/Angle]: + .dimordinate-specify-text-angle-degrees = DIMORDINATE 텍스트 각도(도) 지정: .dimradius-enter-dimension-text-blank-measured = DIMRADIUS Enter 치수 문자(빈 = 측정 값): .dimradius-select-arc-circle-or-polyline-arc = DIMRADIUS 호, 원 또는 폴리선 호 선택: .dimradius-specify-dimension-line-location-text = DIMRADIUS 치수선 위치 지정 [여러 줄 문자/문자/각도]: diff --git a/locales/nl-NL/opencadstudio.ftl b/locales/nl-NL/opencadstudio.ftl index f2a0dd41..bc1bec66 100644 --- a/locales/nl-NL/opencadstudio.ftl +++ b/locales/nl-NL/opencadstudio.ftl @@ -1842,7 +1842,9 @@ annotate = .dimlinear-specify-second-extension-line-origin = DIMLINEAR Vermeld de oorsprong van de tweede extensieregel [Tekst/hoek]: .dimlinear-specify-text-angle-degrees = DIMLINEAR Teksthoek (graden) specificeren: .dimordinate-specify-feature-location = DIMORDINATE Geef functielocatie op: - .dimordinate-specify-leader-endpoint = DIMORDINATE Geef het eindpunt van de verwijslijn op: + .dimordinate-enter-dimension-text-blank-measured = DIMORDINATE Voer maattekst in (leeg = gemeten waarde): + .dimordinate-specify-leader-endpoint = DIMORDINATE Geef het eindpunt van de verwijslijn op [Xdatum/Ydatum/Mtext/Text/Angle]: + .dimordinate-specify-text-angle-degrees = DIMORDINATE Teksthoek (graden) specificeren: .dimradius-enter-dimension-text-blank-measured = DIMRADIUS Voer maattekst in (leeg = gemeten waarde): .dimradius-select-arc-circle-or-polyline-arc = DIMRADIUS Selecteer boog, cirkel of polylijnboog: .dimradius-specify-dimension-line-location-text = DIMRADIUS Geef de positie van de maatlijn op [M-tekst/Tekst/Hoek]: diff --git a/locales/pl-PL/opencadstudio.ftl b/locales/pl-PL/opencadstudio.ftl index 0459de37..01d49a07 100644 --- a/locales/pl-PL/opencadstudio.ftl +++ b/locales/pl-PL/opencadstudio.ftl @@ -1841,7 +1841,9 @@ annotate = .dimlinear-specify-second-extension-line-origin = DIMLINEAR Określ początek drugiej linii pomocniczej [Tekst/Kąt]: .dimlinear-specify-text-angle-degrees = DIMLINEAR Określ kąt tekstu (w stopniach): .dimordinate-specify-feature-location = DIMORDINATE Określ lokalizację elementu: - .dimordinate-specify-leader-endpoint = DIMORDINATE Określ punkt końcowy linii odniesienia: + .dimordinate-enter-dimension-text-blank-measured = DIMORDINATE Wprowadź tekst wymiarowy (puste = wartość zmierzona): + .dimordinate-specify-leader-endpoint = DIMORDINATE Określ punkt końcowy linii odniesienia [Xdatum/Ydatum/Mtext/Text/Angle]: + .dimordinate-specify-text-angle-degrees = DIMORDINATE Określ kąt tekstu (w stopniach): .dimradius-enter-dimension-text-blank-measured = DIMRADIUS Enter tekst wymiarowy (pusta wartość zmierzona =): .dimradius-select-arc-circle-or-polyline-arc = DIMRADIUS Wybierz łuk, okrąg lub łuk polilinii: .dimradius-specify-dimension-line-location-text = DIMRADIUS Określ położenie linii wymiarowej [Mtekst/Tekst/Kąt]: diff --git a/locales/pt-BR/opencadstudio.ftl b/locales/pt-BR/opencadstudio.ftl index 3e939541..65d5bc6f 100644 --- a/locales/pt-BR/opencadstudio.ftl +++ b/locales/pt-BR/opencadstudio.ftl @@ -1842,7 +1842,9 @@ annotate = .dimlinear-specify-second-extension-line-origin = DIMLINEAR Especifique a origem da segunda linha de extensão [Texto/Ângulo]: .dimlinear-specify-text-angle-degrees = DIMLINEAR Especifique o ângulo do texto (graus): .dimordinate-specify-feature-location = DIMORDINATE Especifique a localização da característica: - .dimordinate-specify-leader-endpoint = DIMORDINATE Especifique a extremidade da linha de chamada: + .dimordinate-enter-dimension-text-blank-measured = DIMORDINATE Insira o texto da cota (vazio = valor medido): + .dimordinate-specify-leader-endpoint = DIMORDINATE Especifique a extremidade da linha de chamada [Xdatum/Ydatum/Mtext/Text/Angle]: + .dimordinate-specify-text-angle-degrees = DIMORDINATE Especifique o ângulo do texto (graus): .dimradius-enter-dimension-text-blank-measured = DIMRADIUS Insira o texto da cota (vazio = valor medido): .dimradius-select-arc-circle-or-polyline-arc = DIMRADIUS Selecione um arco, círculo ou arco de polilinha: .dimradius-specify-dimension-line-location-text = DIMRADIUS Especifique a localização da linha de cota [Mtexto/Texto/Ângulo]: diff --git a/locales/ru-RU/opencadstudio.ftl b/locales/ru-RU/opencadstudio.ftl index fde73e1e..bf760ae8 100644 --- a/locales/ru-RU/opencadstudio.ftl +++ b/locales/ru-RU/opencadstudio.ftl @@ -1845,7 +1845,9 @@ annotate = .dimlinear-specify-second-extension-line-origin = DIMLINEAR Укажите происхождение второй линии расширения [Текст/Угле]: .dimlinear-specify-text-angle-degrees = DIMLINEAR Укажите угол текста (градусы): .dimordinate-specify-feature-location = DIMORDINATE Укажите местоположение: - .dimordinate-specify-leader-endpoint = DIMORDINATE Укажите конечную точку выноски: + .dimordinate-enter-dimension-text-blank-measured = DIMORDINATE Введите текст размера (пусто = измеренное значение): + .dimordinate-specify-leader-endpoint = DIMORDINATE Укажите конечную точку выноски [Xdatum/Ydatum/Mtext/Text/Angle]: + .dimordinate-specify-text-angle-degrees = DIMORDINATE Укажите угол текста (градусы): .dimradius-enter-dimension-text-blank-measured = DIMRADIUS Введите текст размера (пусто = измеренное значение): .dimradius-select-arc-circle-or-polyline-arc = DIMRADIUS Выберите дугу, окружность или дуговой сегмент полилинии: .dimradius-specify-dimension-line-location-text = DIMRADIUS Укажите положение размерной линии [Мтекст/Текст/Угол]: diff --git a/locales/tr-TR/opencadstudio.ftl b/locales/tr-TR/opencadstudio.ftl index 38133285..62a06be4 100644 --- a/locales/tr-TR/opencadstudio.ftl +++ b/locales/tr-TR/opencadstudio.ftl @@ -1852,7 +1852,9 @@ annotate = .dimlinear-specify-second-extension-line-origin = DIMLINEAR İkinci uzatma çizgisinin başlangıcını belirtin [Metin/Açı]: .dimlinear-specify-text-angle-degrees = DIMLINEAR Metin açısını belirtin (derece): .dimordinate-specify-feature-location = DIMORDINATE Unsur konumunu belirtin: - .dimordinate-specify-leader-endpoint = DIMORDINATE Kılavuzun uç noktasını belirtin: + .dimordinate-enter-dimension-text-blank-measured = DIMORDINATE Ölçü metnini girin (boş = ölçülen değer): + .dimordinate-specify-leader-endpoint = DIMORDINATE Kılavuzun uç noktasını belirtin [Xdatum/Ydatum/Mtext/Text/Angle]: + .dimordinate-specify-text-angle-degrees = DIMORDINATE Metin açısını belirtin (derece): .dimradius-enter-dimension-text-blank-measured = DIMRADIUS Ölçü metnini girin (boş = ölçülen değer): .dimradius-select-arc-circle-or-polyline-arc = DIMRADIUS Yay, daire veya çoklu çizgi yayı seçin: .dimradius-specify-dimension-line-location-text = DIMRADIUS Ölçü çizgisinin konumunu belirtin [Çok satırlı metin/Metin/Açı]: diff --git a/locales/zh-CN/opencadstudio.ftl b/locales/zh-CN/opencadstudio.ftl index 117a7156..c2ec0095 100644 --- a/locales/zh-CN/opencadstudio.ftl +++ b/locales/zh-CN/opencadstudio.ftl @@ -1829,7 +1829,9 @@ annotate = .dimlinear-specify-second-extension-line-origin = DIMLINEAR 指定第二条尺寸界线原点 [文字/角度]: .dimlinear-specify-text-angle-degrees = DIMLINEAR 指定文字角度(度): .dimordinate-specify-feature-location = DIMORDINATE 指定特征位置: - .dimordinate-specify-leader-endpoint = DIMORDINATE 指定引线端点: + .dimordinate-enter-dimension-text-blank-measured = DIMORDINATE 输入标注文字(空白 = 测量值): + .dimordinate-specify-leader-endpoint = DIMORDINATE 指定引线端点 [Xdatum/Ydatum/Mtext/Text/Angle]: + .dimordinate-specify-text-angle-degrees = DIMORDINATE 指定文字角度(度): .dimradius-enter-dimension-text-blank-measured = DIMRADIUS 输入标注文字(空白 = 测量值): .dimradius-select-arc-circle-or-polyline-arc = DIMRADIUS 选择圆弧、圆或多段线圆弧: .dimradius-specify-dimension-line-location-text = DIMRADIUS 指定尺寸线位置 [多行文字/文字/角度]: diff --git a/locales/zh-TW/opencadstudio.ftl b/locales/zh-TW/opencadstudio.ftl index 3b1f91a6..013d4aca 100644 --- a/locales/zh-TW/opencadstudio.ftl +++ b/locales/zh-TW/opencadstudio.ftl @@ -1841,7 +1841,9 @@ annotate = .dimlinear-specify-second-extension-line-origin = DIMLINEAR 指定第二條尺寸界線原點 [文字/角度]: .dimlinear-specify-text-angle-degrees = DIMLINEAR 指定文字角度(度): .dimordinate-specify-feature-location = DIMORDINATE 指定特徵位置: - .dimordinate-specify-leader-endpoint = DIMORDINATE 指定引線端點: + .dimordinate-enter-dimension-text-blank-measured = DIMORDINATE 輸入標註文字(空白 = 測量值): + .dimordinate-specify-leader-endpoint = DIMORDINATE 指定引線端點 [Xdatum/Ydatum/Mtext/Text/Angle]: + .dimordinate-specify-text-angle-degrees = DIMORDINATE 指定文字角度(度): .dimradius-enter-dimension-text-blank-measured = DIMRADIUS 輸入標註文字(空白 = 測量值): .dimradius-select-arc-circle-or-polyline-arc = DIMRADIUS 選擇圓弧、圓或聚合線圓弧: .dimradius-specify-dimension-line-location-text = DIMRADIUS 指定尺寸線位置 [多行文字/文字/角度]: diff --git a/src/app/command_driver.rs b/src/app/command_driver.rs index de0f1272..8413bc78 100644 --- a/src/app/command_driver.rs +++ b/src/app/command_driver.rs @@ -1279,6 +1279,12 @@ impl OpenCADStudio { .document .header .dimension_associativity; + let single_source_dimension = matches!( + &entity, + acadrust::EntityType::Dimension( + acadrust::entities::Dimension::Ordinate(_) + ) + ); let pending = if association_mode == 0 { let layer = self.tabs[i].active_layer.clone(); if layer != "0" || entity.as_entity().layer().is_empty() { @@ -1339,7 +1345,13 @@ impl OpenCADStudio { .into_iter() .collect() }, - |source| vec![Some(source), Some(source)], + |source| { + if single_source_dimension { + vec![Some(source)] + } else { + vec![Some(source), Some(source)] + } + }, ); self.tabs[i] .scene @@ -3117,7 +3129,6 @@ impl OpenCADStudio { stretched |= mv(&mut d.definition_point); } Dimension::Ordinate(d) => { - stretched |= mv(&mut d.definition_point); stretched |= mv(&mut d.feature_location); stretched |= mv(&mut d.leader_endpoint); } diff --git a/src/app/update/command.rs b/src/app/update/command.rs index e95f6edb..d03ff082 100644 --- a/src/app/update/command.rs +++ b/src/app/update/command.rs @@ -1179,11 +1179,14 @@ pub(super) fn on_tab_close(&mut self, idx: usize) -> Task { .zip(self.tabs[i].selected_grips.iter()) .find(|(owner, g)| **owner == popup.handle && g.id == popup.grip_id) { - // "Move with Leader" drags the whole multileader; the - // others move just the picked grip. + // Only multileaders use the whole-object grip. + let is_multileader = matches!( + self.tabs[i].scene.document.get_entity(popup.handle), + Some(acadrust::EntityType::MultiLeader(_)) + ); let (grip_id, is_translate) = if matches!(item.action, GripMenuAction::MoveWithLeader) - && !is_dimension + && is_multileader { (crate::entities::multileader::MOVE_ALL_GRIP, true) } else { diff --git a/src/entities/dimension.rs b/src/entities/dimension.rs index 22e7f486..ac62e24b 100644 --- a/src/entities/dimension.rs +++ b/src/entities/dimension.rs @@ -158,6 +158,23 @@ fn properties(dim: &Dimension) -> Vec { }], }]; } + if let Dimension::Ordinate(d) = dim { + return vec![PropSection { + title: t!("Misc").into_owned(), + props: vec![ + Property { + label: t!("Dimension style").into_owned(), + field: "style_name", + value: PropValue::PlainText(d.base.style_name.clone()), + }, + edit_angle( + t!("Rotation").as_ref(), + "ordinate_rotation", + -d.base.horizontal_direction.to_degrees(), + ), + ], + }]; + } let mut props = base_props(dim.base()); match dim { Dimension::Aligned(d) => { @@ -385,6 +402,40 @@ fn assign_deg(value: &str, target: &mut f64) -> bool { } fn apply_geom_prop(dim: &mut Dimension, field: &str, value: &str) { + let ordinate_auto_text = match dim { + Dimension::Ordinate(ordinate) if !ordinate.base.text_user_positioned => { + Some(dimension_text_pos_f64(dim, None, 2.5, 1.0)) + } + _ => None, + }; + if let Dimension::Ordinate(ordinate) = dim { + match field { + "ordinate_rotation" => { + if let Some(angle) = parse_f64(value) { + ordinate.base.horizontal_direction = -angle.to_radians(); + ordinate.refresh_measurement(); + } + return; + } + "text_x" | "text_y" => { + let old_text = ordinate_auto_text.unwrap_or(ordinate.base.text_middle_point); + let mut new_text = old_text; + let changed = if field == "text_x" { + assign_f64(value, &mut new_text.x) + } else { + assign_f64(value, &mut new_text.y) + }; + if changed { + let delta = new_text - old_text; + ordinate.leader_endpoint = ordinate.leader_endpoint + delta; + ordinate.base.text_middle_point = new_text; + ordinate.base.text_user_positioned = true; + } + return; + } + _ => {} + } + } if apply_base_prop(dim.base_mut(), field, value) { return; } @@ -743,6 +794,42 @@ fn apply_large_radial_fields(d: &mut DimensionLargeRadial, field: &str, value: & } fn apply_transform(dim: &mut Dimension, t: &EntityTransform) { + if matches!(dim, Dimension::Ordinate(_)) { + match t { + EntityTransform::Translate(delta) => dim.translate(Vector3::new( + delta.x, delta.y, delta.z, + )), + EntityTransform::Rotate { + center, + axis, + angle_rad, + } => crate::scene::view::transform::apply_standard_transform( + dim, + *center, + *axis, + *angle_rad, + ), + EntityTransform::Scale { center, factor } => { + crate::scene::view::transform::apply_standard_scale(dim, *center, *factor) + } + EntityTransform::Mirror { + p1, + p2, + working_normal, + } => acadrust::Entity::apply_transform( + dim, + &crate::scene::view::transform::reflection_about_working_line( + *p1, + *p2, + *working_normal, + ), + ), + EntityTransform::Affine(transform) => { + acadrust::Entity::apply_transform(dim, transform) + } + } + return; + } match t { EntityTransform::Translate(d) => dim.translate(acadrust::types::Vector3::new( d.x as f64, d.y as f64, d.z as f64, @@ -1242,10 +1329,9 @@ impl Grippable for Dimension { center_grip(4, text), ], Dimension::Ordinate(d) => vec![ - square_grip(0, dv3(&d.definition_point)), - center_grip(1, dv3(&d.feature_location)), - center_grip(2, dv3(&d.leader_endpoint)), - center_grip(3, text), + square_grip(0, dv3(&d.feature_location)), + center_grip(1, dv3(&d.leader_endpoint)), + center_grip(2, text), ], Dimension::Arc(d) => { let mut grips = vec![ @@ -1276,13 +1362,26 @@ impl Grippable for Dimension { fn apply_grip(&mut self, grip_id: usize, apply: GripApply) { + if matches!(self, Dimension::Ordinate(_)) && grip_id == 2 { + let old_text = dimension_text_pos_f64(self, None, 2.5, 1.0); + let mut new_text = old_text; + apply_to_v3(&mut new_text, &apply); + let delta = new_text - old_text; + if let Dimension::Ordinate(d) = self { + d.leader_endpoint = d.leader_endpoint + delta; + d.base.text_middle_point = new_text; + d.base.text_user_positioned = true; + d.refresh_measurement(); + } + return; + } // Last grip always moves the text. let text_grip = match self { Dimension::Linear(_) | Dimension::Aligned(_) => 3, Dimension::Radius(_) | Dimension::Diameter(_) => 2, Dimension::Angular2Ln(_) => 5, Dimension::Angular3Pt(_) => 4, - Dimension::Ordinate(_) => 3, + Dimension::Ordinate(_) => 2, Dimension::Arc(d) => if d.has_leader { 6 } else { 4 }, Dimension::LargeRadial(_) => 4, }; @@ -1357,9 +1456,15 @@ impl Grippable for Dimension { _ => {} }, Dimension::Ordinate(d) => match grip_id { - 0 => apply_to_v3(&mut d.definition_point, &apply), - 1 => apply_to_v3(&mut d.feature_location, &apply), - 2 => apply_to_v3(&mut d.leader_endpoint, &apply), + 0 => apply_to_v3(&mut d.feature_location, &apply), + 1 => { + let old = d.leader_endpoint; + apply_to_v3(&mut d.leader_endpoint, &apply); + if d.base.text_user_positioned { + d.base.text_middle_point = + d.base.text_middle_point + (d.leader_endpoint - old); + } + } _ => {} }, Dimension::Arc(d) => match grip_id { @@ -1396,7 +1501,7 @@ impl Grippable for Dimension { Dimension::Radius(_) | Dimension::Diameter(_) => (1, 2), Dimension::Angular2Ln(_) => (4, 5), Dimension::Angular3Pt(_) => (3, 4), - Dimension::Ordinate(_) => (0, 3), + Dimension::Ordinate(_) => (1, 2), Dimension::Arc(d) => (3, if d.has_leader { 6 } else { 4 }), Dimension::LargeRadial(_) => (3, 4), }; @@ -1435,6 +1540,11 @@ impl Grippable for Dimension { action: GripMenuAction::Center, }, ] + } else if matches!(self, Dimension::Ordinate(_)) { + vec![GripMenuItem { + label: "Stretch", + action: GripMenuAction::Stretch, + }] } else if grip_id == dim_line_grip { vec![ GripMenuItem { @@ -1465,7 +1575,7 @@ impl Grippable for Dimension { Dimension::Radius(_) | Dimension::Diameter(_) => (1, 2), Dimension::Angular2Ln(_) => (4, 5), Dimension::Angular3Pt(_) => (3, 4), - Dimension::Ordinate(_) => (0, 3), + Dimension::Ordinate(_) => (1, 2), Dimension::Arc(d) => (3, if d.has_leader { 6 } else { 4 }), Dimension::LargeRadial(_) => (3, 4), }; @@ -1513,7 +1623,7 @@ impl Grippable for Dimension { Dimension::Radius(_) | Dimension::Diameter(_) => 2, Dimension::Angular2Ln(_) => 5, Dimension::Angular3Pt(_) => 4, - Dimension::Ordinate(_) => 3, + Dimension::Ordinate(_) => 2, Dimension::Arc(d) => if d.has_leader { 6 } else { 4 }, Dimension::LargeRadial(_) => 4, }; @@ -2410,7 +2520,6 @@ pub fn style_sections( ], }, ]; - if matches!(dimension, Dimension::Radius(_) | Dimension::Diameter(_)) { let dimcen = real(ov::DIMCEN, s.dimcen); let center_type = if dimcen > 1e-12 { @@ -2561,6 +2670,52 @@ pub fn style_sections( } } + if matches!(dimension, Dimension::Ordinate(_)) { + for section in &mut sections { + section.props.retain(|property| match section.title.as_str() { + title if title == t!("Lines & Arrows").as_ref() => matches!( + property.field, + "dim_arrow_size" + | "dim_ext_line_lineweight" + | "dim_ext_linetype_1" + | "dim_ext_line_1" + | "dim_ext_line_fixed" + | "dim_ext_line_fixed_length" + | "dim_ext_line_color" + | "dim_ext_line_offset" + ), + title if title == t!("Text").as_ref() => !matches!( + property.field, + "dim_text_outside_align" | "dim_text_pos_hor" | "dim_text_inside_align" + ), + title if title == t!("Fit").as_ref() => matches!( + property.field, + "dim_text_movement" | "dim_scale_overall" + ), + _ => true, + }); + } + let dim_scale = if s.dimscale > 1e-6 { s.dimscale } else { 1.0 }; + let text_position = dimension_text_pos_f64( + dimension, + Some(s), + real(ov::DIMTXT, s.dimtxt) * dim_scale, + dim_scale, + ); + for section in &mut sections { + for property in &mut section.props { + match property.field { + "text_x" => { + property.value = PropValue::EditText(format!("{:.4}", text_position.x)); + } + "text_y" => { + property.value = PropValue::EditText(format!("{:.4}", text_position.y)); + } + _ => {} + } + } + } + } sections } @@ -3996,16 +4151,23 @@ fn dimension_geometry( ); } Dimension::Ordinate(d) => { - add_segment( - &mut g.dim_lines, - lv(d.feature_location), - lv(d.definition_point), - ); - add_segment( - &mut g.dim_lines, - lv(d.definition_point), - lv(d.leader_endpoint), - ); + if !suppress.ext1 { + let fixed_length = params + .dimfxlon + .then_some(params.dimfxl.max(0.0) as f64); + let points = d.leader_polyline( + (params.arrow_len * 2.0) as f64, + params.dimexo as f64, + fixed_length, + ); + for pair in points.windows(2) { + let start = lv(pair[0]); + let end = lv(pair[1]); + if (end - start).length_squared() > 1e-12 { + add_segment(&mut g.ext_lines, start, end); + } + } + } } Dimension::Arc(d) => { append_angular_dimension( @@ -4702,7 +4864,6 @@ fn dimension_snap_pts(dim: &Dimension) -> Vec<(glam::DVec3, SnapHint)> { node(d.definition_point), ], Dimension::Ordinate(d) => vec![ - node(d.definition_point), node(d.feature_location), node(d.leader_endpoint), ], @@ -4912,6 +5073,8 @@ fn dimension_text_rotation(dim: &Dimension, style: Option<&DimStyle>) -> f64 { let outside = dimension_text_is_outside(dim, style); if base.text_rotation.abs() > 1e-9 { base.text_rotation + } else if matches!(dim, Dimension::Ordinate(_)) { + dimension_text_natural_rotation(dim) } else if base.horizontal_direction.abs() > 1e-9 { base.horizontal_direction } else if (outside && dimtoh) || (!outside && dimtih) { @@ -5047,6 +5210,14 @@ fn dimension_text_natural_rotation(dim: &Dimension) -> f64 { .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), + Dimension::Ordinate(d) => { + let axis_rotation = -d.base.horizontal_direction; + if d.is_ordinate_type_x { + axis_rotation + std::f64::consts::FRAC_PI_2 + } else { + axis_rotation + } + } _ => 0.0, }; // Clamp to (-π/2, π/2] so text never appears upside-down. @@ -5887,12 +6058,31 @@ fn dimension_text_pos_f64( dimtad, ) } + Dimension::Ordinate(d) => { + let (x_axis, y_axis) = d.local_axes(); + let text_axis = if d.is_ordinate_type_x { y_axis } else { x_axis }; + let perpendicular = if d.is_ordinate_type_x { x_axis } else { y_axis }; + let delta = d.leader_endpoint - d.feature_location; + let direction_sign = if delta.dot(&text_axis) < 0.0 { -1.0 } else { 1.0 }; + let perpendicular_sign = if delta.dot(&perpendicular) < 0.0 { + -1.0 + } else { + 1.0 + }; + let vertical = match dimtad { + 0 => dimtvp * text_height, + 4 => -perp_off, + _ => perp_off, + }; + d.leader_endpoint + + text_axis * (direction_sign * (text_w * 0.5 + dimgap)) + + perpendicular * (perpendicular_sign * vertical) + } _ => { // Auto-placed text follows the style offset. let mid = match dim { Dimension::Angular2Ln(d) => d.dimension_arc, Dimension::Angular3Pt(d) => d.definition_point, - Dimension::Ordinate(d) => d.leader_endpoint, Dimension::Arc(d) => d.definition_point, Dimension::LargeRadial(d) => d.jog_point, _ => base.text_middle_point, diff --git a/src/locale_catalog.rs b/src/locale_catalog.rs index c190e52e..62568e3d 100644 --- a/src/locale_catalog.rs +++ b/src/locale_catalog.rs @@ -775,8 +775,10 @@ pub(super) fn message_attribute(source: &str) -> Option<(&'static str, &'static "DIMLINEAR Specify first extension line origin:" => Some(("annotate", "dimlinear-specify-first-extension-line-origin")), "DIMLINEAR Specify second extension line origin [Text/Angle]:" => Some(("annotate", "dimlinear-specify-second-extension-line-origin")), "DIMLINEAR Specify text angle (degrees):" => Some(("annotate", "dimlinear-specify-text-angle-degrees")), + "DIMORDINATE Enter dimension text (blank = measured value):" => Some(("annotate", "dimordinate-enter-dimension-text-blank-measured")), "DIMORDINATE Specify feature location:" => Some(("annotate", "dimordinate-specify-feature-location")), - "DIMORDINATE Specify leader endpoint:" => Some(("annotate", "dimordinate-specify-leader-endpoint")), + "DIMORDINATE Specify leader endpoint [Xdatum/Ydatum/Mtext/Text/Angle]:" => Some(("annotate", "dimordinate-specify-leader-endpoint")), + "DIMORDINATE Specify text angle (degrees):" => Some(("annotate", "dimordinate-specify-text-angle-degrees")), "DIMRADIUS Enter dimension text (blank = measured value):" => Some(("annotate", "dimradius-enter-dimension-text-blank-measured")), "DIMRADIUS Select arc, circle, or polyline arc:" => Some(("annotate", "dimradius-select-arc-circle-or-polyline-arc")), "DIMRADIUS Specify dimension line location [Mtext/Text/Angle]:" => Some(("annotate", "dimradius-specify-dimension-line-location-text")), diff --git a/src/modules/annotate/ordinate_dim.rs b/src/modules/annotate/ordinate_dim.rs index 203659bf..4ac1d8a1 100644 --- a/src/modules/annotate/ordinate_dim.rs +++ b/src/modules/annotate/ordinate_dim.rs @@ -1,19 +1,11 @@ -// DIMORDINATE command — ordinate (datum) dimension. -// -// Measures the X or Y distance from the UCS origin (datum) to a feature point. -// The user picks: -// 1. The feature location. -// 2. The leader endpoint (where the annotation line ends). -// -// If the leader moves mainly in Y → X-type ordinate (shows X coordinate). -// If the leader moves mainly in X → Y-type ordinate (shows Y coordinate). - use acadrust::entities::{Dimension, DimensionOrdinate}; use acadrust::types::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; @@ -32,9 +24,21 @@ enum Step { LeaderEndpoint { feature: DVec3 }, } +#[derive(Clone, Copy)] +enum DatumMode { + Automatic, + X, + Y, +} + pub struct OrdinateDimCommand { step: Step, plane: WorkingPlane, + datum_mode: DatumMode, + text_override: Option, + awaiting_text: bool, + text_angle: Option, + awaiting_angle: bool, } impl OrdinateDimCommand { @@ -42,6 +46,18 @@ impl OrdinateDimCommand { Self { step: Step::FeaturePoint, plane: WorkingPlane::default(), + datum_mode: DatumMode::Automatic, + text_override: None, + awaiting_text: false, + text_angle: None, + awaiting_angle: false, + } + } + + fn editor_anchor(&self) -> DVec3 { + match self.step { + Step::FeaturePoint => DVec3::ZERO, + Step::LeaderEndpoint { feature } => feature, } } } @@ -56,9 +72,19 @@ impl CadCommand for OrdinateDimCommand { } fn prompt(&self) -> String { + if self.awaiting_text { + return t!("DIMORDINATE Enter dimension text (blank = measured value):") + .into_owned(); + } + if self.awaiting_angle { + return t!("DIMORDINATE Specify text angle (degrees):").into_owned(); + } match self.step { Step::FeaturePoint => t!("DIMORDINATE Specify feature location:").into_owned(), - Step::LeaderEndpoint { .. } => t!("DIMORDINATE Specify leader endpoint:").into_owned(), + Step::LeaderEndpoint { .. } => t!( + "DIMORDINATE Specify leader endpoint [Xdatum/Ydatum/Mtext/Text/Angle]:" + ) + .into_owned(), } } @@ -71,26 +97,138 @@ impl CadCommand for OrdinateDimCommand { Step::LeaderEndpoint { feature } => { let feature = self.plane.to_local(feature); let pt = self.plane.to_local(pt); - let is_x = is_x_type(feature, pt); - let elbow = ordinate_elbow(feature, pt, is_x); + let is_x = match self.datum_mode { + DatumMode::Automatic => is_x_type(feature, pt), + DatumMode::X => true, + DatumMode::Y => false, + }; let mut dim = DimensionOrdinate::new(v3(feature), v3(pt), is_x); - // The leader is an orthogonal L from the feature to the - // endpoint; store its elbow as the definition point. Without it - // the renderer draws feature → (0,0,0) → endpoint, kinking the - // leader through the world origin. The old code also worked in - // the wrong (XZ) plane, dropping the Y coordinate. (#150) - dim.definition_point = v3(elbow); - dim.base.definition_point = v3(elbow); - CmdResult::CommitAndExit(self.plane.place_entity(EntityType::Dimension( - Dimension::Ordinate(dim), - ))) + crate::entities::dimension::set_dimension_text_override( + &mut dim.base, + self.text_override.clone(), + ); + if let Some(angle) = self.text_angle { + dim.base.text_rotation = angle; + } + dim.refresh_measurement(); + CmdResult::CommitDimension { + entity: self.plane.place_entity(EntityType::Dimension( + Dimension::Ordinate(dim), + )), + association: DimensionAssociationInput::Infer(None), + } } } } fn on_enter(&mut self) -> CmdResult { + if self.awaiting_text { + self.awaiting_text = false; + return CmdResult::NeedPoint; + } + if self.awaiting_angle { + self.awaiting_angle = false; + return CmdResult::NeedPoint; + } CmdResult::Cancel } + + fn on_escape(&mut self) -> CmdResult { + CmdResult::Cancel + } + + fn wants_text_input(&self) -> bool { + true + } + + fn point_step_accepts_keywords(&self) -> bool { + !self.awaiting_text && !self.awaiting_angle + } + + fn wants_text_with_spaces(&self) -> bool { + self.awaiting_text + } + + fn options(&self) -> Vec { + if matches!(self.step, Step::LeaderEndpoint { .. }) + && !self.awaiting_text + && !self.awaiting_angle + { + vec![ + CmdOption::new("Xdatum", "XDATUM"), + CmdOption::new("Ydatum", "YDATUM"), + 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 value = text.trim(); + self.text_override = if value.is_empty() || value == "<>" { + None + } else { + Some(value.to_string()) + }; + self.awaiting_text = false; + return Some(CmdResult::NeedPoint); + } + if self.awaiting_angle { + let value = text.trim(); + self.text_angle = if value.is_empty() { + None + } else { + crate::entities::common::parse_typed_angle(value) + }; + self.awaiting_angle = false; + return Some(CmdResult::NeedPoint); + } + if !matches!(self.step, Step::LeaderEndpoint { .. }) { + return None; + } + match text.trim().to_ascii_uppercase().as_str() { + "X" | "XDATUM" => { + self.datum_mode = DatumMode::X; + Some(CmdResult::NeedPoint) + } + "Y" | "YDATUM" => { + self.datum_mode = DatumMode::Y; + Some(CmdResult::NeedPoint) + } + "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) + } + _ => None, + } + } + + 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 on_mouse_move(&mut self, pt: DVec3) -> Option { let feature = match self.step { Step::LeaderEndpoint { feature } => feature, @@ -98,17 +236,23 @@ impl CadCommand for OrdinateDimCommand { }; let feature = self.plane.to_local(feature); let pt = self.plane.to_local(pt); - let is_x = is_x_type(feature, pt); - let elbow = ordinate_elbow(feature, pt, is_x); - let feature = self.plane.to_world(feature); - let elbow = self.plane.to_world(elbow); - let pt = self.plane.to_world(pt); - // Screen-only rubber band: downcast to f32 at the preview boundary. - Some(preview_wire(vec![ - feature.as_vec3(), - elbow.as_vec3(), - pt.as_vec3(), - ])) + let is_x = match self.datum_mode { + DatumMode::Automatic => is_x_type(feature, pt), + DatumMode::X => true, + DatumMode::Y => false, + }; + let dim = DimensionOrdinate::new(v3(feature), v3(pt), is_x); + let points = dim.leader_polyline(0.44, 0.0, None); + Some(preview_wire( + points + .into_iter() + .map(|point| { + self.plane + .to_world(DVec3::new(point.x, point.y, point.z)) + .as_vec3() + }) + .collect(), + )) } } @@ -116,23 +260,10 @@ fn v3(p: DVec3) -> Vector3 { Vector3::new(p.x, p.y, p.z) } -/// X-datum (labels the feature's X coordinate) when the leader runs more -/// vertically than horizontally; Y-datum otherwise. Mirrors the placement -/// decision so the preview and the committed entity agree. fn is_x_type(feature: DVec3, leader: DVec3) -> bool { let dx = (leader.x - feature.x).abs(); let dy = (leader.y - feature.y).abs(); - dy >= dx -} - -/// Orthogonal elbow of the ordinate leader: an X-datum runs along Y from the -/// feature then jogs across in X; a Y-datum runs along X then jogs in Y. -fn ordinate_elbow(feature: DVec3, leader: DVec3, is_x: bool) -> DVec3 { - if is_x { - DVec3::new(feature.x, leader.y, feature.z) - } else { - DVec3::new(leader.x, feature.y, feature.z) - } + dy > dx } fn preview_wire(points: Vec) -> WireModel { @@ -149,9 +280,9 @@ fn preview_wire(points: Vec) -> 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: "dimordinate_preview".into(), points: points.into_iter().map(|p| [p.x, p.y, p.z]).collect(), points_low: Vec::new(), diff --git a/src/modules/draw/modify/explode.rs b/src/modules/draw/modify/explode.rs index c3702e0f..9dff1b97 100644 --- a/src/modules/draw/modify/explode.rs +++ b/src/modules/draw/modify/explode.rs @@ -1179,8 +1179,15 @@ fn explode_dimension(dim: &Dimension, doc: &CadDocument) -> Vec { )); } Dimension::Ordinate(d) => { - result.push(make_seg(&d.feature_location, &d.definition_point, &dim_c)); - result.push(make_seg(&d.definition_point, &d.leader_endpoint, &dim_c)); + if !met.dimse1 { + let fixed_length = met.dimfxlon.then_some(met.dimfxl); + let points = d.leader_polyline(met.dimasz * 2.0, met.dimexo, fixed_length); + for pair in points.windows(2) { + if (pair[1] - pair[0]).length() > 1e-12 { + result.push(make_seg(&pair[0], &pair[1], &ext_c)); + } + } + } } Dimension::Arc(d) => { result.extend(angular_block_segs( diff --git a/src/scene/dimension_assoc.rs b/src/scene/dimension_assoc.rs index ccc3fb9a..43901eea 100644 --- a/src/scene/dimension_assoc.rs +++ b/src/scene/dimension_assoc.rs @@ -381,10 +381,11 @@ fn resolve_reference(scene: &Scene, reference: &AssocDimensionReference) -> Opti .copied() } -fn dimension_inference_points(dimension: &Dimension) -> Option<[Vector3; 2]> { +fn dimension_inference_points(dimension: &Dimension) -> Option<[Option; 2]> { match dimension { - Dimension::Linear(linear) => Some([linear.first_point, linear.second_point]), - Dimension::Aligned(aligned) => Some([aligned.first_point, aligned.second_point]), + Dimension::Linear(linear) => Some([Some(linear.first_point), Some(linear.second_point)]), + Dimension::Aligned(aligned) => Some([Some(aligned.first_point), Some(aligned.second_point)]), + Dimension::Ordinate(ordinate) => Some([Some(ordinate.feature_location), None]), _ => None, } } @@ -420,6 +421,7 @@ fn dimension_reference_points(dimension: &Dimension) -> Vec { angular.angle_vertex, angular.definition_point, ], + Dimension::Ordinate(ordinate) => vec![ordinate.feature_location], _ => Vec::new(), } } @@ -739,7 +741,7 @@ impl Scene { return [None, None]; }; points.map(|point| { - self.document + point.and_then(|point| self.document .entities() .filter(|entity| entity.common().handle != dimension) .filter_map(|entity| { @@ -748,7 +750,7 @@ impl Scene { }) .filter(|(distance, _)| *distance <= 1e-16) .min_by(|first, second| first.0.total_cmp(&second.0)) - .map(|(_, handle)| handle) + .map(|(_, handle)| handle)) }) } @@ -890,6 +892,12 @@ impl Scene { } diameter.base.actual_measurement = diameter.measurement(); } + Dimension::Ordinate(ordinate) => { + if let Some(feature) = resolved[0] { + ordinate.feature_location = feature; + } + ordinate.refresh_measurement(); + } _ => continue, } dimension.base_mut().actual_measurement = dimension.measurement();