diff --git a/locales/ar-SA/opencadstudio.ftl b/locales/ar-SA/opencadstudio.ftl index 34ae4ce3c..77aa9c462 100644 --- a/locales/ar-SA/opencadstudio.ftl +++ b/locales/ar-SA/opencadstudio.ftl @@ -1811,9 +1811,11 @@ annotate = .collect-leaders = تجميع الخطوط القائدة .ddedit-select-text-entity = DDEDIT حدد كيان النص: .dimaligned-enter-dimension-text-blank-measured = DIMALIGNED أدخل نص البُعد (فارغ = القيمة المقاسة): - .dimaligned-specify-dimension-line-location-tex = DIMALIGNED حدد موقع خط البُعد [نص/زاوية]: - .dimaligned-specify-first-extension-line-origin = DIMALIGNED حدد أصل خط الامتداد الأول: - .dimaligned-specify-second-extension-line-origi = DIMALIGNED حدد أصل خط الامتداد الثاني [نص/زاوية]: + .dimaligned-enter-formatted-dimension-text-blank-measured = DIMALIGNED أدخل نص البُعد المنسق (فارغ = القيمة المقاسة): + .dimaligned-select-object-to-dimension = DIMALIGNED حدد كائنًا لقياسه: + .dimaligned-specify-dimension-line-location-tex = DIMALIGNED حدد موقع خط البُعد [Mtext/نص/زاوية]: + .dimaligned-specify-first-extension-line-origin = DIMALIGNED حدد أصل خط الامتداد الأول أو اضغط Enter لتحديد كائن: + .dimaligned-specify-second-extension-line-origi = DIMALIGNED حدد أصل خط الامتداد الثاني: .dimaligned-specify-text-angle-degrees = DIMALIGNED حدد زاوية النص (بالدرجات): .dimangular-specify-angle-vertex = DIMANGULAR حدد رأس الزاوية: .dimangular-specify-dimension-arc-location = DIMANGULAR حدد موقع قوس البُعد: diff --git a/locales/bg-BG/opencadstudio.ftl b/locales/bg-BG/opencadstudio.ftl index 6dbdbd6fa..72ec025d4 100644 --- a/locales/bg-BG/opencadstudio.ftl +++ b/locales/bg-BG/opencadstudio.ftl @@ -1798,9 +1798,11 @@ annotate = .collect-leaders = Събери водачи .ddedit-select-text-entity = DDEDIT Избери текстов обект: .dimaligned-enter-dimension-text-blank-measured = DIMALIGNED Въведи текст на оразмеряване (празно = измерена стойност): - .dimaligned-specify-dimension-line-location-tex = DIMALIGNED Посочи местоположение на линията за оразмеряване [Текст/Ъгъл]: - .dimaligned-specify-first-extension-line-origin = DIMALIGNED Посочи начало на първата удължителна линия: - .dimaligned-specify-second-extension-line-origi = DIMALIGNED Посочи начало на втората удължителна линия [Текст/Ъгъл]: + .dimaligned-enter-formatted-dimension-text-blank-measured = DIMALIGNED Въведи форматиран текст на оразмеряване (празно = измерена стойност): + .dimaligned-select-object-to-dimension = DIMALIGNED Избери обект за оразмеряване: + .dimaligned-specify-dimension-line-location-tex = DIMALIGNED Посочи местоположение на линията за оразмеряване [Mtext/Текст/Ъгъл]: + .dimaligned-specify-first-extension-line-origin = DIMALIGNED Посочи начало на първата удължителна линия или натисни Enter за избор на обект: + .dimaligned-specify-second-extension-line-origi = DIMALIGNED Посочи начало на втората удължителна линия: .dimaligned-specify-text-angle-degrees = DIMALIGNED Посочи ъгъл на текста (градуси): .dimangular-specify-angle-vertex = DIMANGULAR Посочи връх на ъгъла: .dimangular-specify-dimension-arc-location = DIMANGULAR Посочи местоположение на дъгата за оразмеряване: diff --git a/locales/cs-CZ/opencadstudio.ftl b/locales/cs-CZ/opencadstudio.ftl index 67dd4b294..be6c13b87 100644 --- a/locales/cs-CZ/opencadstudio.ftl +++ b/locales/cs-CZ/opencadstudio.ftl @@ -1798,9 +1798,11 @@ annotate = .collect-leaders = Sbírejte vůdce .ddedit-select-text-entity = DDEDIT Vyberte textovou entitu: .dimaligned-enter-dimension-text-blank-measured = Text rozměru DIMALIGNED Enter (prázdná naměřená hodnota =): - .dimaligned-specify-dimension-line-location-tex = DIMALIGNED Určete umístění kótovací čáry [Text/Úhel]: - .dimaligned-specify-first-extension-line-origin = DIMALIGNED Zadejte počátek prvního vynášecího řádku: - .dimaligned-specify-second-extension-line-origi = DIMALIGNED Zadejte počátek druhé vynášecí čáry [Text/Úhel]: + .dimaligned-enter-formatted-dimension-text-blank-measured = DIMALIGNED Zadejte formátovaný text kóty (prázdné = naměřená hodnota): + .dimaligned-select-object-to-dimension = DIMALIGNED Vyberte objekt ke kótování: + .dimaligned-specify-dimension-line-location-tex = DIMALIGNED Určete umístění kótovací čáry [Mtext/Text/Úhel]: + .dimaligned-specify-first-extension-line-origin = DIMALIGNED Zadejte počátek první vynášecí čáry nebo stiskněte Enter pro výběr objektu: + .dimaligned-specify-second-extension-line-origi = DIMALIGNED Zadejte počátek druhé vynášecí čáry: .dimaligned-specify-text-angle-degrees = DIMALIGNED Zadejte úhel textu (stupně): .dimangular-specify-angle-vertex = DIMANGULAR Zadejte vrchol úhlu: .dimangular-specify-dimension-arc-location = DIMANGULAR Zadejte umístění oblouku kóty: diff --git a/locales/de-DE/opencadstudio.ftl b/locales/de-DE/opencadstudio.ftl index 1bb9dbca9..ec9b4e83a 100644 --- a/locales/de-DE/opencadstudio.ftl +++ b/locales/de-DE/opencadstudio.ftl @@ -1799,9 +1799,11 @@ annotate = .collect-leaders = Führungslinien sammeln .ddedit-select-text-entity = DDEDIT Textobjekt auswählen: .dimaligned-enter-dimension-text-blank-measured = DIMALIGNED Bemaßungstext eingeben (leer = Messwert): - .dimaligned-specify-dimension-line-location-tex = DIMALIGNED Lage der Dimensionslinie angeben [Text/Winkel]: - .dimaligned-specify-first-extension-line-origin = DIMALIGNED Geben Sie den Ursprung der ersten Erweiterungslinie an: - .dimaligned-specify-second-extension-line-origi = DIMALIGNED Geben Sie den Ursprung der zweiten Erweiterungslinie an [Text/Winkel]: + .dimaligned-enter-formatted-dimension-text-blank-measured = DIMALIGNED Formatierten Bemaßungstext eingeben (leer = Messwert): + .dimaligned-select-object-to-dimension = DIMALIGNED Zu bemaßendes Objekt auswählen: + .dimaligned-specify-dimension-line-location-tex = DIMALIGNED Lage der Bemaßungslinie angeben [Mtext/Text/Winkel]: + .dimaligned-specify-first-extension-line-origin = DIMALIGNED Ursprung der ersten Maßhilfslinie angeben oder Enter drücken, um ein Objekt auszuwählen: + .dimaligned-specify-second-extension-line-origi = DIMALIGNED Ursprung der zweiten Maßhilfslinie angeben: .dimaligned-specify-text-angle-degrees = DIMALIGNED Textwinkel angeben (Grad): .dimangular-specify-angle-vertex = DIMANGULAR Winkelspitze angeben: .dimangular-specify-dimension-arc-location = DIMANGULAR Bemaßungsbogenlage angeben: diff --git a/locales/en-US/opencadstudio.ftl b/locales/en-US/opencadstudio.ftl index 7b6dd7f8e..55735ad9c 100644 --- a/locales/en-US/opencadstudio.ftl +++ b/locales/en-US/opencadstudio.ftl @@ -1829,9 +1829,11 @@ annotate = .collect-leaders = Collect Leaders .ddedit-select-text-entity = DDEDIT Select text entity: .dimaligned-enter-dimension-text-blank-measured = DIMALIGNED Enter dimension text (blank = measured value): - .dimaligned-specify-dimension-line-location-tex = DIMALIGNED Specify dimension line location [Text/Angle]: - .dimaligned-specify-first-extension-line-origin = DIMALIGNED Specify first extension line origin: - .dimaligned-specify-second-extension-line-origi = DIMALIGNED Specify second extension line origin [Text/Angle]: + .dimaligned-enter-formatted-dimension-text-blank-measured = DIMALIGNED Enter formatted dimension text (blank = measured value): + .dimaligned-select-object-to-dimension = DIMALIGNED Select object to dimension: + .dimaligned-specify-dimension-line-location-tex = DIMALIGNED Specify dimension line location [Mtext/Text/Angle]: + .dimaligned-specify-first-extension-line-origin = DIMALIGNED Specify first extension line origin or press Enter to select object: + .dimaligned-specify-second-extension-line-origi = DIMALIGNED Specify second extension line origin: .dimaligned-specify-text-angle-degrees = DIMALIGNED Specify text angle (degrees): .dimangular-specify-angle-vertex = DIMANGULAR Specify angle vertex: .dimangular-specify-dimension-arc-location = DIMANGULAR Specify dimension arc location: diff --git a/locales/es-ES/opencadstudio.ftl b/locales/es-ES/opencadstudio.ftl index 7c0614338..c071f1a6e 100644 --- a/locales/es-ES/opencadstudio.ftl +++ b/locales/es-ES/opencadstudio.ftl @@ -1799,9 +1799,11 @@ annotate = .collect-leaders = Recopilar directrices .ddedit-select-text-entity = DDEDIT Seleccione una entidad de texto: .dimaligned-enter-dimension-text-blank-measured = DIMALIGNED Introduzca el texto de cota (vacío = valor medido): - .dimaligned-specify-dimension-line-location-tex = DIMALIGNED Especifique la ubicación de la línea de cota [Texto/Ángulo]: - .dimaligned-specify-first-extension-line-origin = DIMALIGNED Especifique el origen de la primera línea de referencia: - .dimaligned-specify-second-extension-line-origi = DIMALIGNED Especifique el origen de la segunda línea de referencia [Texto/Ángulo]: + .dimaligned-enter-formatted-dimension-text-blank-measured = DIMALIGNED Introduzca el texto de cota con formato (vacío = valor medido): + .dimaligned-select-object-to-dimension = DIMALIGNED Seleccione el objeto que desea acotar: + .dimaligned-specify-dimension-line-location-tex = DIMALIGNED Especifique la ubicación de la línea de cota [Mtext/Texto/Ángulo]: + .dimaligned-specify-first-extension-line-origin = DIMALIGNED Especifique el origen de la primera línea de referencia o pulse Enter para seleccionar un objeto: + .dimaligned-specify-second-extension-line-origi = DIMALIGNED Especifique el origen de la segunda línea de referencia: .dimaligned-specify-text-angle-degrees = DIMALIGNED Especifique el ángulo del texto (grados): .dimangular-specify-angle-vertex = DIMANGULAR Especifique el vértice del ángulo: .dimangular-specify-dimension-arc-location = DIMANGULAR Especifique la ubicación del arco de cota: diff --git a/locales/fi-FI/opencadstudio.ftl b/locales/fi-FI/opencadstudio.ftl index 59306d658..8fca52f87 100644 --- a/locales/fi-FI/opencadstudio.ftl +++ b/locales/fi-FI/opencadstudio.ftl @@ -1798,9 +1798,11 @@ annotate = .collect-leaders = Kerää johtajia .ddedit-select-text-entity = DDEDIT Valitse tekstikokonaisuus: .dimaligned-enter-dimension-text-blank-measured = DIMALIGNED Enter mittateksti (tyhjä = mitattu arvo): - .dimaligned-specify-dimension-line-location-tex = DIMALIGNED Määritä mittaviivan sijainti [teksti/kulma]: - .dimaligned-specify-first-extension-line-origin = DIMALIGNED Määritä ensimmäisen jatkolinjan alkuperä: - .dimaligned-specify-second-extension-line-origi = DIMALIGNED Määritä toisen jatkolinjan alkuperä [teksti/kulma]: + .dimaligned-enter-formatted-dimension-text-blank-measured = DIMALIGNED Syötä muotoiltu mittateksti (tyhjä = mitattu arvo): + .dimaligned-select-object-to-dimension = DIMALIGNED Valitse mitoitettava objekti: + .dimaligned-specify-dimension-line-location-tex = DIMALIGNED Määritä mittaviivan sijainti [Mtext/Teksti/Kulma]: + .dimaligned-specify-first-extension-line-origin = DIMALIGNED Määritä ensimmäisen apuviivan alkupiste tai valitse objekti painamalla Enter: + .dimaligned-specify-second-extension-line-origi = DIMALIGNED Määritä toisen apuviivan alkupiste: .dimaligned-specify-text-angle-degrees = DIMALIGNED Määritä tekstin kulma (asteita): .dimangular-specify-angle-vertex = DIMANGULAR Määritä kulman kärkipiste: .dimangular-specify-dimension-arc-location = DIMANGULAR Määritä mittakaaren sijainti: diff --git a/locales/fr-FR/opencadstudio.ftl b/locales/fr-FR/opencadstudio.ftl index fc257706d..85533cafe 100644 --- a/locales/fr-FR/opencadstudio.ftl +++ b/locales/fr-FR/opencadstudio.ftl @@ -1799,9 +1799,11 @@ annotate = .collect-leaders = Regrouper les repères .ddedit-select-text-entity = DDEDIT Sélectionnez l’objet texte : .dimaligned-enter-dimension-text-blank-measured = DIMALIGNED Entrer le texte dimensionnel (blanc = valeur mesurée): - .dimaligned-specify-dimension-line-location-tex = DIMALIGNED Spécifiez la position de la ligne de cote [Texte / Angle] : - .dimaligned-specify-first-extension-line-origin = DIMALIGNED Spécifiez l'origine de la première ligne d'extension: - .dimaligned-specify-second-extension-line-origi = DIMALIGNED Spécifiez l'origine de la deuxième ligne d'extension [Texte/Angle]: + .dimaligned-enter-formatted-dimension-text-blank-measured = DIMALIGNED Saisissez le texte de cote formaté (vide = valeur mesurée) : + .dimaligned-select-object-to-dimension = DIMALIGNED Sélectionnez l'objet à coter : + .dimaligned-specify-dimension-line-location-tex = DIMALIGNED Spécifiez la position de la ligne de cote [Mtext/Texte/Angle] : + .dimaligned-specify-first-extension-line-origin = DIMALIGNED Spécifiez l'origine de la première ligne d'attache ou appuyez sur Entrée pour sélectionner un objet : + .dimaligned-specify-second-extension-line-origi = DIMALIGNED Spécifiez l'origine de la deuxième ligne d'attache : .dimaligned-specify-text-angle-degrees = DIMALIGNED Spécifiez l'angle de texte (degrés): .dimangular-specify-angle-vertex = DIMANGULAR Spécifiez le sommet d'angle: .dimangular-specify-dimension-arc-location = DIMANGULAR Spécifier l'emplacement de l'arc dimensionnel: diff --git a/locales/hi-IN/opencadstudio.ftl b/locales/hi-IN/opencadstudio.ftl index f6b779702..98e00312f 100644 --- a/locales/hi-IN/opencadstudio.ftl +++ b/locales/hi-IN/opencadstudio.ftl @@ -1787,9 +1787,11 @@ annotate = .collect-leaders = लीडर एकत्र करें .ddedit-select-text-entity = DDEDIT टेक्स्ट ऑब्जेक्ट चुनें: .dimaligned-enter-dimension-text-blank-measured = DIMALIGNED आयाम टेक्स्ट दर्ज करें (blank = मापा मान): - .dimaligned-specify-dimension-line-location-tex = DIMALIGNED आयाम लाइन स्थान निर्दिष्ट करें [टेक्स्ट / एंगल]: - .dimaligned-specify-first-extension-line-origin = DIMALIGNED पहली एक्सटेंशन लाइन उत्पत्ति निर्दिष्ट करें: - .dimaligned-specify-second-extension-line-origi = DIMALIGNED दूसरी एक्सटेंशन लाइन उत्पत्ति निर्दिष्ट करें [टेक्स्ट / एंगल]: + .dimaligned-enter-formatted-dimension-text-blank-measured = DIMALIGNED स्वरूपित आयाम टेक्स्ट दर्ज करें (खाली = मापा मान): + .dimaligned-select-object-to-dimension = DIMALIGNED आयाम देने के लिए ऑब्जेक्ट चुनें: + .dimaligned-specify-dimension-line-location-tex = DIMALIGNED आयाम रेखा का स्थान निर्दिष्ट करें [Mtext/टेक्स्ट/कोण]: + .dimaligned-specify-first-extension-line-origin = DIMALIGNED पहली एक्सटेंशन रेखा का मूल निर्दिष्ट करें या ऑब्जेक्ट चुनने के लिए Enter दबाएँ: + .dimaligned-specify-second-extension-line-origi = DIMALIGNED दूसरी एक्सटेंशन रेखा का मूल निर्दिष्ट करें: .dimaligned-specify-text-angle-degrees = DIMALIGNED पाठ कोण निर्दिष्ट करें (डिग्री): .dimangular-specify-angle-vertex = DIMANGULAR कोण वर्टेक्स निर्दिष्ट करें: .dimangular-specify-dimension-arc-location = DIMANGULAR आयाम आर्क स्थान निर्दिष्ट करें: diff --git a/locales/hu-HU/opencadstudio.ftl b/locales/hu-HU/opencadstudio.ftl index 3f7061c51..1c9530c8c 100644 --- a/locales/hu-HU/opencadstudio.ftl +++ b/locales/hu-HU/opencadstudio.ftl @@ -1798,9 +1798,11 @@ annotate = .collect-leaders = Gyűjtsd össze a vezetőket .ddedit-select-text-entity = DDEDIT Szöveg entitás kiválasztása: .dimaligned-enter-dimension-text-blank-measured = DIMALIGNED Enter méretszöveg (üres = mért érték): - .dimaligned-specify-dimension-line-location-tex = DIMALIGNED A méretvonal helyének megadása [szöveg/szög]: - .dimaligned-specify-first-extension-line-origin = DIMALIGNED Adja meg az első mellékvonal eredetét: - .dimaligned-specify-second-extension-line-origi = DIMALIGNED Adja meg a második mellékvonal eredetét [szöveg/szög]: + .dimaligned-enter-formatted-dimension-text-blank-measured = DIMALIGNED Adja meg a formázott méretszöveget (üres = mért érték): + .dimaligned-select-object-to-dimension = DIMALIGNED Válassza ki a méretezendő objektumot: + .dimaligned-specify-dimension-line-location-tex = DIMALIGNED Adja meg a méretvonal helyét [Mtext/Szöveg/Szög]: + .dimaligned-specify-first-extension-line-origin = DIMALIGNED Adja meg az első segédvonal kezdőpontját, vagy nyomja meg az Entert egy objektum kiválasztásához: + .dimaligned-specify-second-extension-line-origi = DIMALIGNED Adja meg a második segédvonal kezdőpontját: .dimaligned-specify-text-angle-degrees = DIMALIGNED Adja meg a szöveg szögét (fokban): .dimangular-specify-angle-vertex = DIMANGULAR Szögcsúcs megadása: .dimangular-specify-dimension-arc-location = DIMANGULAR A méretív helyének megadása: diff --git a/locales/it-IT/opencadstudio.ftl b/locales/it-IT/opencadstudio.ftl index 4a743466e..a81cf31d9 100644 --- a/locales/it-IT/opencadstudio.ftl +++ b/locales/it-IT/opencadstudio.ftl @@ -1798,9 +1798,11 @@ annotate = .collect-leaders = Colleziona leader .ddedit-select-text-entity = DDEDIT Seleziona entità testo: .dimaligned-enter-dimension-text-blank-measured = Testo della dimensione DIMALIGNED Enter (valore misurato = vuoto): - .dimaligned-specify-dimension-line-location-tex = DIMALIGNED Specificare la posizione della linea di quota [Testo/Angolo]: - .dimaligned-specify-first-extension-line-origin = DIMALIGNED Specificare l'origine della prima linea di estensione: - .dimaligned-specify-second-extension-line-origi = DIMALIGNED Specificare l'origine della seconda linea di estensione [Testo/Angolo]: + .dimaligned-enter-formatted-dimension-text-blank-measured = DIMALIGNED Immettere il testo di quota formattato (vuoto = valore misurato): + .dimaligned-select-object-to-dimension = DIMALIGNED Selezionare l'oggetto da quotare: + .dimaligned-specify-dimension-line-location-tex = DIMALIGNED Specificare la posizione della linea di quota [Mtext/Testo/Angolo]: + .dimaligned-specify-first-extension-line-origin = DIMALIGNED Specificare l'origine della prima linea di estensione o premere Invio per selezionare un oggetto: + .dimaligned-specify-second-extension-line-origi = DIMALIGNED Specificare l'origine della seconda linea di estensione: .dimaligned-specify-text-angle-degrees = DIMALIGNED Specificare l'angolo del testo (gradi): .dimangular-specify-angle-vertex = DIMANGULAR Specificare il vertice dell'angolo: .dimangular-specify-dimension-arc-location = DIMANGULAR Specificare la posizione dell'arco di quota: diff --git a/locales/ja-JP/opencadstudio.ftl b/locales/ja-JP/opencadstudio.ftl index 16b42a35e..bcdf18a31 100644 --- a/locales/ja-JP/opencadstudio.ftl +++ b/locales/ja-JP/opencadstudio.ftl @@ -1789,9 +1789,11 @@ annotate = .collect-leaders = 引出線を収集 .ddedit-select-text-entity = DDEDIT 文字図形を選択: .dimaligned-enter-dimension-text-blank-measured = DIMALIGNED 寸法値を入力(空白 = 計測値): - .dimaligned-specify-dimension-line-location-tex = DIMALIGNED 寸法線の位置を指定 [文字/角度]: - .dimaligned-specify-first-extension-line-origin = DIMALIGNED 1 本目の寸法補助線の起点を指定: - .dimaligned-specify-second-extension-line-origi = DIMALIGNED 2 本目の寸法補助線の起点を指定 [文字/角度]: + .dimaligned-enter-formatted-dimension-text-blank-measured = DIMALIGNED 書式付き寸法文字を入力(空白 = 計測値): + .dimaligned-select-object-to-dimension = DIMALIGNED 寸法を記入するオブジェクトを選択: + .dimaligned-specify-dimension-line-location-tex = DIMALIGNED 寸法線の位置を指定 [Mtext/文字/角度]: + .dimaligned-specify-first-extension-line-origin = DIMALIGNED 1 本目の寸法補助線の起点を指定、または Enter でオブジェクトを選択: + .dimaligned-specify-second-extension-line-origi = DIMALIGNED 2 本目の寸法補助線の起点を指定: .dimaligned-specify-text-angle-degrees = DIMALIGNED 文字角度を指定(度): .dimangular-specify-angle-vertex = DIMANGULAR 角度の頂点を指定: .dimangular-specify-dimension-arc-location = DIMANGULAR 寸法円弧の位置を指定: diff --git a/locales/ko-KR/opencadstudio.ftl b/locales/ko-KR/opencadstudio.ftl index 971a807be..7337e4e7d 100644 --- a/locales/ko-KR/opencadstudio.ftl +++ b/locales/ko-KR/opencadstudio.ftl @@ -1798,9 +1798,11 @@ annotate = .collect-leaders = 리더 수집 .ddedit-select-text-entity = DDEDIT 텍스트 엔터티 선택: .dimaligned-enter-dimension-text-blank-measured = DIMALIGNED Enter 치수 문자(빈 = 측정 값): - .dimaligned-specify-dimension-line-location-tex = DIMALIGNED 치수선 위치 지정 [문자/각도]: - .dimaligned-specify-first-extension-line-origin = DIMALIGNED 첫 번째 연장선 원점 지정: - .dimaligned-specify-second-extension-line-origi = DIMALIGNED 두 번째 연장선 원점 지정 [문자/각도]: + .dimaligned-enter-formatted-dimension-text-blank-measured = DIMALIGNED 서식 있는 치수 문자를 입력하십시오(비워 두면 측정값): + .dimaligned-select-object-to-dimension = DIMALIGNED 치수를 기입할 객체 선택: + .dimaligned-specify-dimension-line-location-tex = DIMALIGNED 치수선 위치 지정 [Mtext/문자/각도]: + .dimaligned-specify-first-extension-line-origin = DIMALIGNED 첫 번째 치수 보조선 원점을 지정하거나 Enter를 눌러 객체 선택: + .dimaligned-specify-second-extension-line-origi = DIMALIGNED 두 번째 치수 보조선 원점 지정: .dimaligned-specify-text-angle-degrees = DIMALIGNED 텍스트 각도(도) 지정: .dimangular-specify-angle-vertex = DIMANGULAR 각도 꼭지점 지정: .dimangular-specify-dimension-arc-location = DIMANGULAR 치수 호 위치를 지정합니다. diff --git a/locales/nl-NL/opencadstudio.ftl b/locales/nl-NL/opencadstudio.ftl index 3e63979bf..034260b2b 100644 --- a/locales/nl-NL/opencadstudio.ftl +++ b/locales/nl-NL/opencadstudio.ftl @@ -1799,9 +1799,11 @@ annotate = .collect-leaders = Verwijslijnen verzamelen .ddedit-select-text-entity = DDEDIT Selecteer een tekstobject: .dimaligned-enter-dimension-text-blank-measured = DIMALIGNED Voer maattekst in (leeg = gemeten waarde): - .dimaligned-specify-dimension-line-location-tex = DIMALIGNED Geef de positie van de maatlijn op [Tekst/Hoek]: - .dimaligned-specify-first-extension-line-origin = DIMALIGNED Vermeld de oorsprong van de eerste extensieregel: - .dimaligned-specify-second-extension-line-origi = DIMALIGNED Vermeld de oorsprong van de tweede extensieregel [Tekst/hoek]: + .dimaligned-enter-formatted-dimension-text-blank-measured = DIMALIGNED Voer opgemaakte maattekst in (leeg = gemeten waarde): + .dimaligned-select-object-to-dimension = DIMALIGNED Selecteer het object om te bematen: + .dimaligned-specify-dimension-line-location-tex = DIMALIGNED Geef de positie van de maatlijn op [Mtext/Tekst/Hoek]: + .dimaligned-specify-first-extension-line-origin = DIMALIGNED Geef het beginpunt van de eerste hulplijn op of druk op Enter om een object te selecteren: + .dimaligned-specify-second-extension-line-origi = DIMALIGNED Geef het beginpunt van de tweede hulplijn op: .dimaligned-specify-text-angle-degrees = DIMALIGNED Teksthoek (graden) specificeren: .dimangular-specify-angle-vertex = DIMANGULAR Specificeer hoekvertex: .dimangular-specify-dimension-arc-location = DIMANGULAR Geef de positie van de maatboog op: diff --git a/locales/pl-PL/opencadstudio.ftl b/locales/pl-PL/opencadstudio.ftl index 946df99c4..d270e31de 100644 --- a/locales/pl-PL/opencadstudio.ftl +++ b/locales/pl-PL/opencadstudio.ftl @@ -1798,9 +1798,11 @@ annotate = .collect-leaders = Zbieraj Liderów .ddedit-select-text-entity = DDEDIT Wybierz element tekstowy: .dimaligned-enter-dimension-text-blank-measured = DIMALIGNED Enter tekst wymiarowy (pusta wartość zmierzona =): - .dimaligned-specify-dimension-line-location-tex = DIMALIGNED Określ położenie linii wymiarowej [Tekst/Kąt]: - .dimaligned-specify-first-extension-line-origin = DIMALIGNED Określ początek pierwszej linii pomocniczej: - .dimaligned-specify-second-extension-line-origi = DIMALIGNED Określ początek drugiej linii pomocniczej [Tekst/Kąt]: + .dimaligned-enter-formatted-dimension-text-blank-measured = DIMALIGNED Wprowadź sformatowany tekst wymiaru (puste = zmierzona wartość): + .dimaligned-select-object-to-dimension = DIMALIGNED Wybierz obiekt do zwymiarowania: + .dimaligned-specify-dimension-line-location-tex = DIMALIGNED Określ położenie linii wymiarowej [Mtext/Tekst/Kąt]: + .dimaligned-specify-first-extension-line-origin = DIMALIGNED Określ początek pierwszej linii pomocniczej lub naciśnij Enter, aby wybrać obiekt: + .dimaligned-specify-second-extension-line-origi = DIMALIGNED Określ początek drugiej linii pomocniczej: .dimaligned-specify-text-angle-degrees = DIMALIGNED Określ kąt tekstu (w stopniach): .dimangular-specify-angle-vertex = DIMANGULAR Określ wierzchołek kąta: .dimangular-specify-dimension-arc-location = DIMANGULAR Określ położenie łuku wymiarowego: diff --git a/locales/pt-BR/opencadstudio.ftl b/locales/pt-BR/opencadstudio.ftl index 1ccfdd355..5cf6e6569 100644 --- a/locales/pt-BR/opencadstudio.ftl +++ b/locales/pt-BR/opencadstudio.ftl @@ -1799,9 +1799,11 @@ annotate = .collect-leaders = Coletar linhas de chamada .ddedit-select-text-entity = DDEDIT Selecione a entidade de texto: .dimaligned-enter-dimension-text-blank-measured = DIMALIGNED Insira o texto da cota (vazio = valor medido): - .dimaligned-specify-dimension-line-location-tex = DIMALIGNED Especifique a localização da linha de cota [Texto/Ângulo]: - .dimaligned-specify-first-extension-line-origin = DIMALIGNED Especifique a origem da primeira linha de extensão: - .dimaligned-specify-second-extension-line-origi = DIMALIGNED Especifique a origem da segunda linha de extensão [Texto/Ângulo]: + .dimaligned-enter-formatted-dimension-text-blank-measured = DIMALIGNED Insira o texto formatado da cota (vazio = valor medido): + .dimaligned-select-object-to-dimension = DIMALIGNED Selecione o objeto a ser cotado: + .dimaligned-specify-dimension-line-location-tex = DIMALIGNED Especifique a localização da linha de cota [Mtext/Texto/Ângulo]: + .dimaligned-specify-first-extension-line-origin = DIMALIGNED Especifique a origem da primeira linha de extensão ou pressione Enter para selecionar um objeto: + .dimaligned-specify-second-extension-line-origi = DIMALIGNED Especifique a origem da segunda linha de extensão: .dimaligned-specify-text-angle-degrees = DIMALIGNED Especifique o ângulo do texto (graus): .dimangular-specify-angle-vertex = DIMANGULAR Especifique o vértice do ângulo: .dimangular-specify-dimension-arc-location = DIMANGULAR Especifique a localização do arco de cota: diff --git a/locales/ru-RU/opencadstudio.ftl b/locales/ru-RU/opencadstudio.ftl index a1020e34a..f861524ba 100644 --- a/locales/ru-RU/opencadstudio.ftl +++ b/locales/ru-RU/opencadstudio.ftl @@ -1802,9 +1802,11 @@ annotate = .collect-leaders = Собрать выноски .ddedit-select-text-entity = DDEDIT Выберите текстовый объект: .dimaligned-enter-dimension-text-blank-measured = DIMALIGNED Введите текст размера (пусто = измеренное значение): - .dimaligned-specify-dimension-line-location-tex = DIMALIGNED Укажите положение размерной линии [Текст/Угол]: - .dimaligned-specify-first-extension-line-origin = DIMALIGNED Укажите происхождение первой линии расширения: - .dimaligned-specify-second-extension-line-origi = DIMALIGNED Укажите происхождение второй линии расширения [Текст/Угле]: + .dimaligned-enter-formatted-dimension-text-blank-measured = DIMALIGNED Введите форматированный текст размера (пусто = измеренное значение): + .dimaligned-select-object-to-dimension = DIMALIGNED Выберите объект для нанесения размера: + .dimaligned-specify-dimension-line-location-tex = DIMALIGNED Укажите положение размерной линии [Mtext/Текст/Угол]: + .dimaligned-specify-first-extension-line-origin = DIMALIGNED Укажите начало первой выносной линии или нажмите Enter для выбора объекта: + .dimaligned-specify-second-extension-line-origi = DIMALIGNED Укажите начало второй выносной линии: .dimaligned-specify-text-angle-degrees = DIMALIGNED Укажите угол текста (градусы): .dimangular-specify-angle-vertex = DIMANGULAR Укажите угол вершины: .dimangular-specify-dimension-arc-location = DIMANGULAR Укажите местоположение дуги размерности: diff --git a/locales/tr-TR/opencadstudio.ftl b/locales/tr-TR/opencadstudio.ftl index f9ffa60fd..5c5568dbf 100644 --- a/locales/tr-TR/opencadstudio.ftl +++ b/locales/tr-TR/opencadstudio.ftl @@ -1809,9 +1809,11 @@ annotate = .collect-leaders = Kılavuzları Topla .ddedit-select-text-entity = DDEDIT Metin nesnesini seçin: .dimaligned-enter-dimension-text-blank-measured = DIMALIGNED Ölçü metnini girin (boş = ölçülen değer): - .dimaligned-specify-dimension-line-location-tex = DIMALIGNED Ölçü çizgisinin konumunu belirtin [Metin/Açı]: - .dimaligned-specify-first-extension-line-origin = DIMALIGNED Birinci uzatma çizgisinin başlangıcını belirtin: - .dimaligned-specify-second-extension-line-origi = DIMALIGNED İkinci uzatma çizgisinin başlangıcını belirtin [Metin/Açı]: + .dimaligned-enter-formatted-dimension-text-blank-measured = DIMALIGNED Biçimlendirilmiş ölçü metnini girin (boş = ölçülen değer): + .dimaligned-select-object-to-dimension = DIMALIGNED Ölçülendirilecek nesneyi seçin: + .dimaligned-specify-dimension-line-location-tex = DIMALIGNED Ölçü çizgisinin konumunu belirtin [Mtext/Metin/Açı]: + .dimaligned-specify-first-extension-line-origin = DIMALIGNED Birinci uzatma çizgisinin başlangıcını belirtin veya nesne seçmek için Enter'a basın: + .dimaligned-specify-second-extension-line-origi = DIMALIGNED İkinci uzatma çizgisinin başlangıcını belirtin: .dimaligned-specify-text-angle-degrees = DIMALIGNED Metin açısını belirtin (derece): .dimangular-specify-angle-vertex = DIMANGULAR Açı köşesini belirtin: .dimangular-specify-dimension-arc-location = DIMANGULAR Ölçü yayının konumunu belirtin: diff --git a/locales/zh-CN/opencadstudio.ftl b/locales/zh-CN/opencadstudio.ftl index 9e2747c66..945366b0d 100644 --- a/locales/zh-CN/opencadstudio.ftl +++ b/locales/zh-CN/opencadstudio.ftl @@ -1786,9 +1786,11 @@ annotate = .collect-leaders = 合并引线 .ddedit-select-text-entity = DDEDIT 选择文字实体: .dimaligned-enter-dimension-text-blank-measured = DIMALIGNED 输入标注文字(空白 = 测量值): - .dimaligned-specify-dimension-line-location-tex = DIMALIGNED 指定尺寸线位置 [文字/角度]: - .dimaligned-specify-first-extension-line-origin = DIMALIGNED 指定第一条尺寸界线原点: - .dimaligned-specify-second-extension-line-origi = DIMALIGNED 指定第二条尺寸界线原点 [文字/角度]: + .dimaligned-enter-formatted-dimension-text-blank-measured = DIMALIGNED 输入带格式的标注文字(空白 = 测量值): + .dimaligned-select-object-to-dimension = DIMALIGNED 选择要标注的对象: + .dimaligned-specify-dimension-line-location-tex = DIMALIGNED 指定尺寸线位置 [Mtext/文字/角度]: + .dimaligned-specify-first-extension-line-origin = DIMALIGNED 指定第一条尺寸界线原点,或按 Enter 选择对象: + .dimaligned-specify-second-extension-line-origi = DIMALIGNED 指定第二条尺寸界线原点: .dimaligned-specify-text-angle-degrees = DIMALIGNED 指定文字角度(度): .dimangular-specify-angle-vertex = DIMANGULAR 指定角度顶点: .dimangular-specify-dimension-arc-location = DIMANGULAR 指定标注圆弧位置: diff --git a/locales/zh-TW/opencadstudio.ftl b/locales/zh-TW/opencadstudio.ftl index 634e171b5..075ec02fd 100644 --- a/locales/zh-TW/opencadstudio.ftl +++ b/locales/zh-TW/opencadstudio.ftl @@ -1798,9 +1798,11 @@ annotate = .collect-leaders = 合併引線 .ddedit-select-text-entity = DDEDIT 選擇文字實體: .dimaligned-enter-dimension-text-blank-measured = DIMALIGNED 輸入標註文字(空白 = 測量值): - .dimaligned-specify-dimension-line-location-tex = DIMALIGNED 指定尺寸線位置 [文字/角度]: - .dimaligned-specify-first-extension-line-origin = DIMALIGNED 指定第一條尺寸界線原點: - .dimaligned-specify-second-extension-line-origi = DIMALIGNED 指定第二條尺寸界線原點 [文字/角度]: + .dimaligned-enter-formatted-dimension-text-blank-measured = DIMALIGNED 輸入帶格式的標註文字(空白 = 測量值): + .dimaligned-select-object-to-dimension = DIMALIGNED 選取要標註的物件: + .dimaligned-specify-dimension-line-location-tex = DIMALIGNED 指定尺寸線位置 [Mtext/文字/角度]: + .dimaligned-specify-first-extension-line-origin = DIMALIGNED 指定第一條尺寸界線原點,或按 Enter 選取物件: + .dimaligned-specify-second-extension-line-origi = DIMALIGNED 指定第二條尺寸界線原點: .dimaligned-specify-text-angle-degrees = DIMALIGNED 指定文字角度(度): .dimangular-specify-angle-vertex = DIMANGULAR 指定角度頂點: .dimangular-specify-dimension-arc-location = DIMANGULAR 指定標註圓弧位置: diff --git a/src/app/command_driver.rs b/src/app/command_driver.rs index bf03b591f..d35a32259 100644 --- a/src/app/command_driver.rs +++ b/src/app/command_driver.rs @@ -801,19 +801,24 @@ impl OpenCADStudio { // the structure snapshot fallback. let delta_safe = self.delta_add_safe(i, &entity); let pending = self.begin_undo(i, label, 1, delta_safe); - let is_linear_dimension = matches!( + let is_associative_dimension = matches!( entity, - acadrust::EntityType::Dimension(acadrust::entities::Dimension::Linear(_)) + acadrust::EntityType::Dimension( + acadrust::entities::Dimension::Linear(_) + | acadrust::entities::Dimension::Aligned(_) + ) ); + let association_enabled = + self.tabs[i].scene.document.header.dimension_associativity == 2; let committed = self.commit_entity_handle(entity); - if is_linear_dimension { + if is_associative_dimension && association_enabled { if let Some(handle) = committed { let sources = self.tabs[i] .scene - .infer_linear_dimension_sources(handle); + .infer_dimension_sources(handle); self.tabs[i] .scene - .attach_linear_dimension_association(handle, sources); + .attach_dimension_association(handle, sources); } } self.tabs[i].dirty = true; @@ -1205,19 +1210,24 @@ impl OpenCADStudio { let label = self.history_label_from_active_cmd(i, "ENTITY"); let delta_safe = self.delta_add_safe(i, &entity); let pending = self.begin_undo(i, label, 1, delta_safe); - let is_linear_dimension = matches!( + let is_associative_dimension = matches!( entity, - acadrust::EntityType::Dimension(acadrust::entities::Dimension::Linear(_)) + acadrust::EntityType::Dimension( + acadrust::entities::Dimension::Linear(_) + | acadrust::entities::Dimension::Aligned(_) + ) ); + let association_enabled = + self.tabs[i].scene.document.header.dimension_associativity == 2; let committed = self.commit_entity_handle(entity); - if is_linear_dimension { + if is_associative_dimension && association_enabled { if let Some(handle) = committed { let sources = self.tabs[i] .scene - .infer_linear_dimension_sources(handle); + .infer_dimension_sources(handle); self.tabs[i] .scene - .attach_linear_dimension_association(handle, sources); + .attach_dimension_association(handle, sources); } } self.tabs[i].dirty = true; @@ -1229,25 +1239,87 @@ impl OpenCADStudio { self.commit_undo_delta(i, pd); } } - CmdResult::CommitAssociativeDimension { entity, source } => { - let label = self.history_label_from_active_cmd(i, "DIMLINEAR"); - let pending = self.begin_undo(i, label, 1, false); - if let Some(handle) = self.commit_entity_handle(entity) { - self.tabs[i] + CmdResult::CommitDimension { mut entity, source } => { + let label = self.history_label_from_active_cmd(i, "DIMENSION"); + let association_mode = self.tabs[i] + .scene + .document + .header + .dimension_associativity; + let pending = if association_mode == 0 { + let layer = self.tabs[i].active_layer.clone(); + if layer != "0" || entity.as_entity().layer().is_empty() { + entity.as_entity_mut().set_layer(layer); + } + crate::scene::view::dispatch::apply_color( + &mut entity, + self.ribbon.active_color, + ); + crate::scene::view::dispatch::apply_common_prop( + &mut entity, + "linetype", + &self.ribbon.active_linetype.clone(), + ); + crate::scene::view::dispatch::apply_line_weight( + &mut entity, + self.ribbon.active_lineweight, + ); + let celtscale = self.tabs[i] .scene - .attach_linear_dimension_association(handle, [Some(source), Some(source)]); - self.tabs[i].scene.bump_entities(&[ - (handle, crate::scene::ChangeKind::Modified), - (source, crate::scene::ChangeKind::Modified), - ]); - } + .document + .header + .current_entity_linetype_scale; + if (celtscale - 1.0).abs() > 1e-9 && celtscale.abs() > 1e-9 { + entity.common_mut().linetype_scale = celtscale; + } + crate::scene::creation_style::apply_current_creation_styles( + &self.tabs[i].scene.document, + &mut entity, + ); + let pieces = crate::modules::draw::modify::explode::explode_entity( + &entity, + &self.tabs[i].scene.document, + ); + let delta_safe = pieces + .iter() + .all(|piece| self.delta_add_safe(i, piece)); + let pending = self.begin_undo(i, label, pieces.len(), delta_safe); + for piece in pieces { + self.tabs[i].scene.add_entity(piece); + } + pending + } else { + let delta_safe = self.delta_add_safe(i, &entity); + let pending = self.begin_undo(i, label, 1, delta_safe); + if let Some(handle) = self.commit_entity_handle(entity) { + if association_mode == 2 { + let sources = source.map_or_else( + || self.tabs[i].scene.infer_dimension_sources(handle), + |source| [Some(source), Some(source)], + ); + self.tabs[i] + .scene + .attach_dimension_association(handle, sources); + let mut changes = vec![ + (handle, crate::scene::ChangeKind::Modified), + ]; + changes.extend(sources.into_iter().flatten().map(|source| { + (source, crate::scene::ChangeKind::Modified) + })); + changes.sort_by_key(|(handle, _)| handle.value()); + changes.dedup_by_key(|(handle, _)| handle.value()); + self.tabs[i].scene.bump_entities(&changes); + } + } + pending + }; self.tabs[i].dirty = true; self.tabs[i].scene.clear_preview_wire(); self.tabs[i].active_cmd = None; self.tabs[i].snap_result = None; self.restore_pre_cmd_tangent(); - if let Some(pending) = pending { - self.commit_undo_delta(i, pending); + if let Some(pd) = pending { + self.commit_undo_delta(i, pd); } } CmdResult::CommitSolid { diff --git a/src/command.rs b/src/command.rs index 89b8d0382..797b27b4b 100644 --- a/src/command.rs +++ b/src/command.rs @@ -1212,10 +1212,11 @@ pub enum CmdResult { CommitEntitiesAndExit(Vec), /// Commit an acadrust entity to the document and end the command. CommitAndExit(EntityType), - /// Commit an object-selected linear dimension and retain its source link. - CommitAssociativeDimension { + /// Commit a linear/aligned dimension using the drawing's association mode. + /// Object-selection workflows may retain their source. + CommitDimension { entity: EntityType, - source: Handle, + source: Option, }, /// Commit a Model-tab 3D solid: the acadrust entity (for selection / /// persistence) plus its B-rep (cached for boolean ops + shaded diff --git a/src/entities/dimension.rs b/src/entities/dimension.rs index ad6cd235a..ae3032661 100644 --- a/src/entities/dimension.rs +++ b/src/entities/dimension.rs @@ -86,8 +86,21 @@ fn base_props(base: &DimensionBase) -> Vec Vec { - if let Dimension::Linear(d) = dim { - let base = &d.base; + let compact_linear = match dim { + Dimension::Linear(d) => Some(( + &d.base, + d.rotation, + d.ext_line_rotation, + )), + Dimension::Aligned(d) => Some(( + &d.base, + (d.second_point.y - d.first_point.y) + .atan2(d.second_point.x - d.first_point.x), + d.ext_line_rotation, + )), + _ => None, + }; + if let Some((base, rotation, ext_line_rotation)) = compact_linear { return vec![PropSection { title: t!("Misc").into_owned(), props: vec![ @@ -98,11 +111,15 @@ fn properties(dim: &Dimension) -> Vec { base.style_name.clone(), ), }, - edit_angle(t!("Dim line angle").as_ref(), "rotation", d.rotation.to_degrees()), + edit_angle( + t!("Dim line angle").as_ref(), + "rotation", + rotation.to_degrees(), + ), edit_angle( t!("Extension line angle").as_ref(), "ext_line_rotation", - d.ext_line_rotation.to_degrees(), + ext_line_rotation.to_degrees(), ), ], }]; @@ -354,6 +371,29 @@ fn apply_geom_prop(dim: &mut Dimension, field: &str, value: &str) { } fn apply_linear_fields_aligned(d: &mut DimensionAligned, field: &str, value: &str) { + if field == "rotation" { + let Some(angle) = parse_f64(value).map(f64::to_radians) else { + return; + }; + let old_angle = (d.second_point.y - d.first_point.y) + .atan2(d.second_point.x - d.first_point.x); + let delta = angle - old_angle; + let origin_x = d.first_point.x; + let origin_y = d.first_point.y; + let rotate = |point: &mut acadrust::types::Vector3| { + let x = point.x - origin_x; + let y = point.y - origin_y; + let (sin, cos) = delta.sin_cos(); + point.x = origin_x + x * cos - y * sin; + point.y = origin_y + x * sin + y * cos; + }; + rotate(&mut d.second_point); + rotate(&mut d.definition_point); + rotate(&mut d.base.definition_point); + rotate(&mut d.base.text_middle_point); + rotate(&mut d.base.insertion_point); + return; + } apply_linear_common( &mut d.first_point, &mut d.second_point, @@ -1495,6 +1535,7 @@ pub fn style_sections( let s = style; let dimfxlon = int(ov::DIMFXLON, s.dimfxlon as i16) != 0; + let dimtix = int(ov::DIMTIX, s.dimtix as i16) != 0; let dimlunit = int(ov::DIMLUNIT, s.dimlunit); let dimfrac = int(ov::DIMFRAC, s.dimfrac); let dimalt = int(ov::DIMALT, s.dimalt as i16) != 0; @@ -1859,7 +1900,7 @@ pub fn style_sections( "dim_text_inside_align", on(int(ov::DIMTIH, s.dimtih as i16) != 0), &["On", "Off"], - true, + dimtix, ), property( t!("Text position X").as_ref(), @@ -1925,7 +1966,7 @@ pub fn style_sections( choice( t!("Text inside").as_ref(), "dim_text_inside", - on(int(ov::DIMTIX, s.dimtix as i16) != 0), + on(dimtix), &["On", "Off"], true, ), @@ -2192,14 +2233,14 @@ pub fn style_sections( "dim_tolerance_pos_vert", tolerance_vertical_label(int(ov::DIMTOLJ, s.dimtolj)), &["Bottom", "Middle", "Top"], - tolerance_enabled, + true, ), choice( t!("Tolerance alignment").as_ref(), "dim_tolerance_alignment", tolerance_alignment_label(int(ov::DIMTALN, 0)), &["Align decimal separators", "Align operational symbols"], - tolerance_display == "Deviation", + true, ), choice( t!("Tolerance suppress leading zeros").as_ref(), @@ -4443,16 +4484,20 @@ fn alternate_units_text(measurement: f64, style: Option<&DimStyle>) -> Option 1e-12; + // DIMALTMZF replaces the ordinary alternate-unit factor for sub-unit + // values; it is not an additional multiplier. + let mut v = if use_sub_units { + measurement * s.dimaltmzf + } else { + scaled + }; if s.dimaltrnd > 1e-12 { v = (v / s.dimaltrnd).round() * s.dimaltrnd; } - let use_sub_units = s.dimaltz & 4 != 0 - && v.abs() < 1.0 - && s.dimaltmzf.abs() > 1e-12; - if use_sub_units { - v *= s.dimaltmzf; - } let dec = s.dimaltd.max(0) as usize; let raw = format_with_unit(v, s.dimaltu, dec, s.dimfrac, s.dimaltz, true); let suppressed = apply_linear_zero_suppression(&raw, s.dimaltz); @@ -4460,12 +4505,17 @@ fn alternate_units_text(measurement: f64, style: Option<&DimStyle>) -> Option String { - let raw = format!("{:.*}", alttdec, x * s.dimaltf); + let raw = format!("{:.*}", alttdec, x * tolerance_factor); swap_decimal_sep(&apply_linear_zero_suppression(&raw, alttzin), s.dimdsep) }; if (s.dimtp - s.dimtm).abs() < 1e-12 && s.dimtp.abs() > 1e-12 { @@ -4479,7 +4529,7 @@ fn alternate_units_text(measurement: f64, style: Option<&DimStyle>) -> Option String { - let raw = format!("{:.*}", alttdec, x * s.dimaltf); + let raw = format!("{:.*}", alttdec, x * tolerance_factor); swap_decimal_sep(&apply_linear_zero_suppression(&raw, alttzin), s.dimdsep) }; format!( @@ -4618,14 +4668,18 @@ fn format_linear_value(measurement: f64, style: Option<&DimStyle>) -> String { .unwrap_or((4, 8, 1.0, 0.0, 46, 2, 0, 1.0, "")); let lfac = if lfac.abs() < 1e-12 { 1.0 } else { lfac }; - let mut v = measurement * lfac; + let scaled = measurement * lfac; + let use_sub_units = zin & 4 != 0 && scaled.abs() < 1.0 && sub_factor.abs() > 1e-12; + // For values below one unit, DIMMZF replaces DIMLFAC; applying it after + // DIMLFAC multiplies both factors and reports the wrong sub-unit value. + let mut v = if use_sub_units { + measurement * sub_factor + } else { + scaled + }; if rnd > 1e-12 { v = (v / rnd).round() * rnd; } - let use_sub_units = zin & 4 != 0 && v.abs() < 1.0 && sub_factor.abs() > 1e-12; - if use_sub_units { - v *= sub_factor; - } let dec = dec.max(0) as usize; let raw = format_with_unit(v, lunit, dec, frac, zin, false); let suppressed = apply_linear_zero_suppression(&raw, zin); diff --git a/src/locale_catalog.rs b/src/locale_catalog.rs index eb7ea9f5c..10273e2c6 100644 --- a/src/locale_catalog.rs +++ b/src/locale_catalog.rs @@ -726,8 +726,13 @@ pub(super) fn message_attribute(source: &str) -> Option<(&'static str, &'static "DDEDIT: selected entity is not text." => Some(("draw", "ddedit-selected-entity-is-not-text")), "DDEDIT: text updated." => Some(("common", "ddedit-text-updated")), "DIMALIGNED Enter dimension text (blank = measured value):" => Some(("annotate", "dimaligned-enter-dimension-text-blank-measured")), + "DIMALIGNED Enter formatted dimension text (blank = measured value):" => Some(("annotate", "dimaligned-enter-formatted-dimension-text-blank-measured")), + "DIMALIGNED Select object to dimension:" => Some(("annotate", "dimaligned-select-object-to-dimension")), + "DIMALIGNED Specify dimension line location [Mtext/Text/Angle]:" => Some(("annotate", "dimaligned-specify-dimension-line-location-tex")), "DIMALIGNED Specify dimension line location [Text/Angle]:" => Some(("annotate", "dimaligned-specify-dimension-line-location-tex")), + "DIMALIGNED Specify first extension line origin or press Enter to select object:" => Some(("annotate", "dimaligned-specify-first-extension-line-origin")), "DIMALIGNED Specify first extension line origin:" => Some(("annotate", "dimaligned-specify-first-extension-line-origin")), + "DIMALIGNED Specify second extension line origin:" => Some(("annotate", "dimaligned-specify-second-extension-line-origi")), "DIMALIGNED Specify second extension line origin [Text/Angle]:" => Some(("annotate", "dimaligned-specify-second-extension-line-origi")), "DIMALIGNED Specify text angle (degrees):" => Some(("annotate", "dimaligned-specify-text-angle-degrees")), "DIMANGULAR Specify angle vertex:" => Some(("annotate", "dimangular-specify-angle-vertex")), diff --git a/src/modules/annotate/aligned_dim.rs b/src/modules/annotate/aligned_dim.rs index 81fa87865..c7cac1cdc 100644 --- a/src/modules/annotate/aligned_dim.rs +++ b/src/modules/annotate/aligned_dim.rs @@ -1,7 +1,7 @@ // DIMALIGNED command — aligned dimension (measures true distance between two points). use acadrust::entities::{Dimension, DimensionAligned}; -use acadrust::types::Vector3; +use acadrust::types::{Handle, Vector3}; use acadrust::EntityType; use glam::DVec3; @@ -38,6 +38,10 @@ pub struct AlignedDimensionCommand { text_angle: Option, /// True while the next typed value is captured as the text angle. awaiting_angle: bool, + selecting_object: bool, + picked_entity: Option, + source_handle: Option, + mtext_override: bool, } impl AlignedDimensionCommand { @@ -49,6 +53,10 @@ impl AlignedDimensionCommand { awaiting_text: false, text_angle: None, awaiting_angle: false, + selecting_object: false, + picked_entity: None, + source_handle: None, + mtext_override: false, } } } @@ -64,18 +72,29 @@ impl CadCommand for AlignedDimensionCommand { fn prompt(&self) -> String { if self.awaiting_text { - return t!("DIMALIGNED Enter dimension text (blank = measured value):").into_owned(); + return if self.mtext_override { + t!("DIMALIGNED Enter formatted dimension text (blank = measured value):") + .into_owned() + } else { + t!("DIMALIGNED Enter dimension text (blank = measured value):").into_owned() + }; } if self.awaiting_angle { return t!("DIMALIGNED Specify text angle (degrees):").into_owned(); } + if self.selecting_object { + return t!("DIMALIGNED Select object to dimension:").into_owned(); + } match self.step { - Step::First => t!("DIMALIGNED Specify first extension line origin:").into_owned(), + Step::First => t!( + "DIMALIGNED Specify first extension line origin or press Enter to select object:" + ) + .into_owned(), Step::Second(_) => { - t!("DIMALIGNED Specify second extension line origin [Text/Angle]:").into_owned() + t!("DIMALIGNED Specify second extension line origin:").into_owned() } Step::DimLine { .. } => { - t!("DIMALIGNED Specify dimension line location [Text/Angle]:").into_owned() + t!("DIMALIGNED Specify dimension line location [Mtext/Text/Angle]:").into_owned() } } } @@ -87,6 +106,9 @@ impl CadCommand for AlignedDimensionCommand { CmdResult::NeedPoint } Step::Second(p1) => { + if pt.distance_squared(p1) <= 1e-24 { + return CmdResult::NeedPoint; + } self.step = Step::DimLine { p1, p2: pt }; CmdResult::NeedPoint } @@ -95,29 +117,25 @@ impl CadCommand for AlignedDimensionCommand { let p2 = self.plane.to_local(p2); let pt = self.plane.to_local(pt); let mut dim = DimensionAligned::new(v3(p1), v3(p2)); - // The dimension line runs through the cursor: store it as the - // definition point and let the renderer project it onto the - // line perpendicular (same as the preview and DIMLINEAR). - // - // The old path called `set_offset` with the straight-line - // p2→cursor *distance*, which `set_offset` then re-applies along - // the line perpendicular — placing the line at the wrong - // perpendicular distance and always on the +perp side, so it - // never matched the preview the user was dragging. (#150) + // Store the cursor position so commit matches the preview. dim.definition_point = v3(pt); dim.base.definition_point = v3(pt); let (d1, d2) = dim_line_endpoints(p1, p2, pt); dim.base.text_middle_point = v3((d1 + d2) * 0.5); dim.base.insertion_point = dim.base.text_middle_point; dim.base.actual_measurement = dim.measurement(); - dim.base.user_text = self.text_override.clone(); + crate::entities::dimension::set_dimension_text_override( + &mut dim.base, + self.text_override.clone(), + ); // An explicit text angle overrides the default rotation. if let Some(a) = self.text_angle { dim.base.text_rotation = a; } - CmdResult::CommitAndExit(self.plane.place_entity(EntityType::Dimension( - Dimension::Aligned(dim), - ))) + CmdResult::CommitDimension { + entity: self.plane.place_entity(EntityType::Dimension(Dimension::Aligned(dim))), + source: self.source_handle, + } } } } @@ -132,6 +150,10 @@ impl CadCommand for AlignedDimensionCommand { self.awaiting_angle = false; return CmdResult::NeedPoint; } + if matches!(self.step, Step::First) { + self.selecting_object = true; + return CmdResult::NeedPoint; + } CmdResult::Cancel } @@ -173,8 +195,17 @@ impl CadCommand for AlignedDimensionCommand { self.awaiting_angle = false; return Some(CmdResult::NeedPoint); } + if !matches!(self.step, Step::DimLine { .. }) { + return None; + } match text.trim().to_uppercase().as_str() { - "T" | "TEXT" | "M" | "MTEXT" => { + "T" | "TEXT" => { + self.mtext_override = false; + self.awaiting_text = true; + Some(CmdResult::NeedPoint) + } + "M" | "MTEXT" => { + self.mtext_override = true; self.awaiting_text = true; Some(CmdResult::NeedPoint) } @@ -186,6 +217,38 @@ impl CadCommand for AlignedDimensionCommand { } } + fn needs_entity_pick(&self) -> bool { + self.selecting_object + } + + 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((p1, p2)) = super::linear_dim::dimension_source_points(&entity, point) else { + return CmdResult::NeedPoint; + }; + if p1.distance_squared(p2) <= 1e-24 { + return CmdResult::NeedPoint; + } + self.source_handle = Some(handle); + self.selecting_object = false; + self.step = Step::DimLine { p1, p2 }; + CmdResult::NeedPoint + } + fn on_mouse_move(&mut self, pt: DVec3) -> Option { let (p1, p2) = match self.step { Step::First => return None, @@ -272,13 +335,15 @@ fn dim_line_endpoints(p1: DVec3, p2: DVec3, dim_pt: DVec3) -> (DVec3, DVec3) { } fn preview_aligned(p1: DVec3, p2: DVec3, dim_pt: DVec3) -> WireModel { - // Show ext lines + dim line. let (d1, d2) = dim_line_endpoints(p1, p2, dim_pt); - // Preview WireModel points are screen/GPU-side: downcast to f32. - let p1 = p1.as_vec3(); - let p2 = p2.as_vec3(); - let d1 = d1.as_vec3(); - let d2 = d2.as_vec3(); + let axis = (d2 - d1).normalize_or_zero(); + let perp = DVec3::new(-axis.y, axis.x, 0.0); + let nan = [f32::NAN, 0.0, 0.0]; + let arrow = 0.22; + let text = (d1 + d2) * 0.5 + perp * 0.15; + let half_width = ((p2 - p1).length().log10().max(0.0) + 1.0) * 0.18; + let half_height = 0.16; + let to_point = |point: DVec3| point.as_vec3().to_array(); WireModel { point_marker: None, taper_widths: Vec::new(), @@ -292,19 +357,33 @@ fn preview_aligned(p1: DVec3, p2: DVec3, dim_pt: DVec3) -> 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: "dimaligned_preview".into(), points: vec![ - [p1.x, p1.y, p1.z], - [d1.x, d1.y, d1.z], - [f32::NAN, 0.0, 0.0], - [p2.x, p2.y, p2.z], - [d2.x, d2.y, d2.z], - [f32::NAN, 0.0, 0.0], - [d1.x, d1.y, d1.z], - [d2.x, d2.y, d2.z], + to_point(p1), + to_point(d1), + nan, + to_point(p2), + to_point(d2), + nan, + to_point(d1), + to_point(d2), + nan, + to_point(d1 + axis * arrow + perp * arrow * 0.45), + to_point(d1), + to_point(d1 + axis * arrow - perp * arrow * 0.45), + nan, + to_point(d2 - axis * arrow + perp * arrow * 0.45), + to_point(d2), + to_point(d2 - axis * arrow - perp * arrow * 0.45), + nan, + to_point(text - axis * half_width - perp * half_height), + to_point(text + axis * half_width - perp * half_height), + to_point(text + axis * half_width + perp * half_height), + to_point(text - axis * half_width + perp * half_height), + to_point(text - axis * half_width - perp * half_height), ], points_low: Vec::new(), color: WireModel::CYAN, diff --git a/src/modules/annotate/linear_dim.rs b/src/modules/annotate/linear_dim.rs index a3768011c..00c2bd56f 100644 --- a/src/modules/annotate/linear_dim.rs +++ b/src/modules/annotate/linear_dim.rs @@ -1,7 +1,9 @@ use acadrust::entities::{Dimension, DimensionLinear}; use acadrust::types::Vector3; use acadrust::EntityType; -use cadkernel::geom2d::{closest_point, Curve, Line as KernelLine}; +use cadkernel::geom2d::{ + closest_point, Circle as KernelCircle, Curve, Line as KernelLine, +}; use crate::command::{CadCommand, CmdResult, WorkingPlane}; use crate::modules::{IconKind, ModuleEvent, ToolDef}; @@ -9,18 +11,7 @@ use crate::scene::model::wire_model::WireModel; use glam::DVec3; use crate::t; -/// Which axis a linear dimension measures along. -/// -/// Not the segment's own direction. A linear dimension reports the run or the -/// rise, and which of the two is wanted is said by where the dimension line is -/// put: pulled clear of the points above or below, the horizontal distance is -/// what is left to show; pulled out to the side, the vertical one. Taking the -/// answer from the two origins alone made every shallow tilt horizontal -/// forever, whatever the cursor did. (#669) -/// -/// "Clear of the points" is measured against their extent rather than their -/// midpoint: a dimension line dragged straight up from near one end of a long -/// pair is still above them, though it is a long way from the middle. +/// Select the measured axis from where the dimension line clears the points. fn measure_axis(first: DVec3, second: DVec3, def: DVec3) -> DVec3 { let outside = |value: f64, a: f64, b: f64| { let (low, high) = if a <= b { (a, b) } else { (b, a) }; @@ -193,10 +184,9 @@ impl CadCommand for LinearDimensionCommand { let entity = self.plane.place_entity(EntityType::Dimension( Dimension::Linear(dim), )); - if let Some(source) = self.source_handle { - CmdResult::CommitAssociativeDimension { entity, source } - } else { - CmdResult::CommitAndExit(entity) + CmdResult::CommitDimension { + entity, + source: self.source_handle, } } } @@ -366,11 +356,31 @@ fn dimension_line_offset(second: DVec3, point: DVec3, axis: DVec3) -> f64 { (point - second).dot(perpendicular) } -fn dimension_source_points(entity: &EntityType, click: DVec3) -> Option<(DVec3, DVec3)> { +pub(crate) fn dimension_source_points( + entity: &EntityType, + click: DVec3, +) -> Option<(DVec3, DVec3)> { let point = |p: Vector3| DVec3::new(p.x, p.y, p.z); match entity { EntityType::Line(line) => Some((point(line.start), point(line.end))), EntityType::Arc(arc) => Some((point(arc.start_point_wcs()), point(arc.end_point_wcs()))), + EntityType::Circle(circle) => { + let click = crate::scene::view::transform::wcs_point_to_ocs( + (click.x, click.y, click.z), + (circle.normal.x, circle.normal.y, circle.normal.z), + ); + let curve = Curve::Circle(KernelCircle { + centre: [circle.center.x, circle.center.y], + radius: circle.radius, + }); + let first = closest_point(&curve, [click.0, click.1]).point; + let parameter = curve.parameter_at(first); + let second = curve.point_at((parameter + 0.5).rem_euclid(1.0)); + Some(( + ocs_point(first, circle.center.z, circle.normal), + ocs_point(second, circle.center.z, circle.normal), + )) + } EntityType::LwPolyline(polyline) => nearest_planar_source( polyline .vertices diff --git a/src/scene/dimension_assoc.rs b/src/scene/dimension_assoc.rs index bda8f168e..2814695ea 100644 --- a/src/scene/dimension_assoc.rs +++ b/src/scene/dimension_assoc.rs @@ -5,6 +5,10 @@ use acadrust::objects::{ }; use acadrust::types::{Handle, Vector3}; use acadrust::EntityType; +use cadkernel::geom2d::{ + closest_point, Circle as KernelCircle, Curve as KernelCurve, +}; +use std::f64::consts::TAU; use super::{ChangeKind, Scene}; @@ -23,6 +27,13 @@ fn ocs_point(x: f64, y: f64, elevation: f64, normal: Vector3) -> Vector3 { Vector3::new(point.0, point.1, point.2) } +fn circle_curve(circle: &acadrust::entities::Circle) -> KernelCurve { + KernelCurve::Circle(KernelCircle { + centre: [circle.center.x, circle.center.y], + radius: circle.radius, + }) +} + fn source_points(entity: &EntityType) -> Vec { match entity { EntityType::Line(line) => vec![line.start, line.end], @@ -56,6 +67,9 @@ fn source_points(entity: &EntityType) -> Vec { } fn source_marker(entity: &EntityType, point: Vector3) -> Option { + if matches!(entity, EntityType::Circle(_)) { + return Some(0); + } source_points(entity) .into_iter() .enumerate() @@ -69,11 +83,73 @@ fn source_marker(entity: &EntityType, point: Vector3) -> Option { fn resolve_reference(scene: &Scene, reference: &AssocDimensionReference) -> Option { let source = *reference.xrefs.first()?; let entity = scene.document.get_entity(source)?; + if let EntityType::Circle(circle) = entity { + let stored = crate::scene::view::transform::wcs_point_to_ocs( + ( + reference.osnap_point.x, + reference.osnap_point.y, + reference.osnap_point.z, + ), + (circle.normal.x, circle.normal.y, circle.normal.z), + ); + let curve = circle_curve(circle); + let stored_parameter = curve.parameter_at([stored.0, stored.1]) * TAU; + let parameter = if reference.osnap_distance.abs() > 1e-12 + || stored_parameter.abs() <= 1e-12 + { + reference.osnap_distance + } else { + stored_parameter + }; + let parameter = if parameter.is_finite() { parameter } else { 0.0 }; + let point = curve.point_at(parameter / TAU); + return Some(ocs_point( + point[0], + point[1], + circle.center.z, + circle.normal, + )); + } source_points(entity) .get(reference.main_gs_marker.max(0) as usize) .copied() } +fn dimension_points(dimension: &Dimension) -> Option<[Vector3; 2]> { + match dimension { + Dimension::Linear(linear) => Some([linear.first_point, linear.second_point]), + Dimension::Aligned(aligned) => Some([aligned.first_point, aligned.second_point]), + _ => None, + } +} + +fn source_distance_squared(entity: &EntityType, point: Vector3) -> Option { + if let EntityType::Circle(circle) = entity { + let point = crate::scene::view::transform::wcs_point_to_ocs( + (point.x, point.y, point.z), + (circle.normal.x, circle.normal.y, circle.normal.z), + ); + let radial_error = closest_point(&circle_curve(circle), [point.0, point.1]).distance; + let plane_error = point.2 - circle.center.z; + return Some(radial_error * radial_error + plane_error * plane_error); + } + source_points(entity) + .into_iter() + .map(|candidate| point_distance_squared(candidate, point)) + .min_by(f64::total_cmp) +} + +fn source_parameter(entity: &EntityType, point: Vector3) -> f64 { + let EntityType::Circle(circle) = entity else { + return 0.0; + }; + let point = crate::scene::view::transform::wcs_point_to_ocs( + (point.x, point.y, point.z), + (circle.normal.x, circle.normal.y, circle.normal.z), + ); + circle_curve(circle).parameter_at([point.0, point.1]) * TAU +} + pub(crate) fn dimension_is_associative( document: &acadrust::CadDocument, dimension: Handle, @@ -97,34 +173,49 @@ pub(crate) fn dimension_is_associative( } impl Scene { - pub(crate) fn attach_linear_dimension_association( + pub(crate) fn attach_dimension_association( &mut self, dimension: Handle, sources: [Option; 2], ) { - let Some(EntityType::Dimension(Dimension::Linear(linear))) = - self.document.get_entity(dimension) + let Some(EntityType::Dimension(entity)) = self.document.get_entity(dimension) else { return; }; - let first_point = linear.first_point; - let second_point = linear.second_point; - let source_data = [first_point, second_point].map(|point| point); - let resolved: [Option<(Handle, i32)>; 2] = std::array::from_fn(|index| { + let Some(source_data) = dimension_points(entity) else { + return; + }; + let resolved: [Option<(Handle, i32, f64, u8)>; 2] = std::array::from_fn(|index| { let source = sources[index]?; let entity = self.document.get_entity(source)?; - source_marker(entity, source_data[index]).map(|marker| (source, marker)) + source_marker(entity, source_data[index]).map(|marker| { + ( + source, + marker, + source_parameter(entity, source_data[index]), + if matches!(entity, EntityType::Circle(_)) { + 10 + } else { + 1 + }, + ) + }) }); if resolved.iter().all(Option::is_none) { return; } - let reference = |source: Handle, marker: i32, point: Vector3| AssocDimensionReference { + let reference = |source: Handle, + marker: i32, + parameter: f64, + osnap_type: u8, + point: Vector3| AssocDimensionReference { class_name: "AcDbOsnapPointRef".to_string(), - osnap_type: 1, + osnap_type, xrefs: vec![source], main_subent_type: 1, main_gs_marker: marker, + osnap_distance: parameter, osnap_point: point, ..AssocDimensionReference::default() }; @@ -132,9 +223,15 @@ impl Scene { std::array::from_fn(|_| Vec::new()); let mut associativity = 0; for (index, resolved) in resolved.into_iter().enumerate() { - if let Some((source, marker)) = resolved { + if let Some((source, marker, parameter, osnap_type)) = resolved { associativity |= 1 << index; - references[index].push(reference(source, marker, source_data[index])); + references[index].push(reference( + source, + marker, + parameter, + osnap_type, + source_data[index], + )); } } @@ -165,24 +262,23 @@ impl Scene { } } - pub(crate) fn infer_linear_dimension_sources( + pub(crate) fn infer_dimension_sources( &self, dimension: Handle, ) -> [Option; 2] { - let Some(EntityType::Dimension(Dimension::Linear(linear))) = - self.document.get_entity(dimension) + let Some(EntityType::Dimension(entity)) = self.document.get_entity(dimension) else { return [None, None]; }; - [linear.first_point, linear.second_point].map(|point| { + let Some(points) = dimension_points(entity) else { + return [None, None]; + }; + points.map(|point| { self.document .entities() .filter(|entity| entity.common().handle != dimension) .filter_map(|entity| { - source_points(entity) - .into_iter() - .map(|candidate| point_distance_squared(candidate, point)) - .min_by(f64::total_cmp) + source_distance_squared(entity, point) .map(|distance| (distance, entity.common().handle)) }) .filter(|(distance, _)| *distance <= 1e-16) @@ -231,19 +327,35 @@ impl Scene { if first.is_none() && second.is_none() { continue; } - if let Some(EntityType::Dimension(Dimension::Linear(linear))) = + let Some(EntityType::Dimension(dimension)) = self.document.get_entity_mut(association.dimension) - { - if let Some(first) = first { - linear.first_point = first; + else { + continue; + }; + match dimension { + Dimension::Linear(linear) => { + if let Some(first) = first { + linear.first_point = first; + } + if let Some(second) = second { + linear.second_point = second; + } + linear.base.actual_measurement = linear.measurement(); + linear.base.definition_point = linear.definition_point; } - if let Some(second) = second { - linear.second_point = second; + Dimension::Aligned(aligned) => { + if let Some(first) = first { + aligned.first_point = first; + } + if let Some(second) = second { + aligned.second_point = second; + } + aligned.base.actual_measurement = aligned.measurement(); + aligned.base.definition_point = aligned.definition_point; } - linear.base.actual_measurement = linear.measurement(); - linear.base.definition_point = linear.definition_point; - refreshed.push((association.dimension, ChangeKind::Modified)); + _ => continue, } + refreshed.push((association.dimension, ChangeKind::Modified)); } refreshed }