diff --git a/Cargo.lock b/Cargo.lock index 661be0bc6..875643b27 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4205,7 +4205,7 @@ dependencies = [ [[package]] name = "opencadcodec" version = "0.6.0" -source = "git+https://github.com/HakanSeven12/opencadcodec.git?rev=c9ffcac#c9ffcac5ecdc7a504cc4a7e3ecb52ac9d587c8bf" +source = "git+https://github.com/HakanSeven12/opencadcodec.git?rev=8189f83#8189f833574c544fc57a1d773591014c3a5907c9" dependencies = [ "anyhow", "bitflags 2.13.1", @@ -4228,7 +4228,7 @@ dependencies = [ [[package]] name = "opencadgraph" version = "0.1.0" -source = "git+https://github.com/HakanSeven12/opencadgraph.git?rev=7f6aae7#7f6aae7aff6b7de87cc1dcdb38a06c3e64ae1922" +source = "git+https://github.com/HakanSeven12/opencadgraph.git?rev=d3558bb#d3558bb1ccd63d3819fa0358267bac1ba21ab593" dependencies = [ "opencadkernel", "serde_json", @@ -4237,7 +4237,7 @@ dependencies = [ [[package]] name = "opencadkernel" version = "0.1.0" -source = "git+https://github.com/HakanSeven12/opencadkernel.git?rev=99b6b48#99b6b4890704d300596ba502b5a1c8ec1eefa954" +source = "git+https://github.com/HakanSeven12/opencadkernel.git?rev=a82f17d#a82f17dd34af0787023c93ed565220dd1467ff46" dependencies = [ "cavalier_contours", "opencadcodec", @@ -4248,7 +4248,7 @@ dependencies = [ [[package]] name = "opencadkernel-constraints" version = "0.1.0" -source = "git+https://github.com/HakanSeven12/opencadkernel.git?rev=99b6b48#99b6b4890704d300596ba502b5a1c8ec1eefa954" +source = "git+https://github.com/HakanSeven12/opencadkernel.git?rev=a82f17d#a82f17dd34af0787023c93ed565220dd1467ff46" dependencies = [ "nalgebra", ] diff --git a/Cargo.toml b/Cargo.toml index c9480bb41..f62e0ef45 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,10 +34,10 @@ rfd = "0.17" clap = { version = "4", features = ["derive", "string"] } env_logger = "0.11" log = "0.4" -codec = { package = "opencadcodec", git = "https://github.com/HakanSeven12/opencadcodec.git", rev = "c9ffcac", features = ["serde"] } -kernel = { package = "opencadkernel", git = "https://github.com/HakanSeven12/opencadkernel.git", rev = "99b6b48", features = ["acis", "offset"] } -kernel-constraints = { package = "opencadkernel-constraints", git = "https://github.com/HakanSeven12/opencadkernel.git", rev = "99b6b48" } -graph = { package = "opencadgraph", git = "https://github.com/HakanSeven12/opencadgraph.git", rev = "7f6aae7" } +codec = { package = "opencadcodec", git = "https://github.com/HakanSeven12/opencadcodec.git", rev = "8189f83", features = ["serde"] } +kernel = { package = "opencadkernel", git = "https://github.com/HakanSeven12/opencadkernel.git", rev = "a82f17d", features = ["acis", "offset"] } +kernel-constraints = { package = "opencadkernel-constraints", git = "https://github.com/HakanSeven12/opencadkernel.git", rev = "a82f17d" } +graph = { package = "opencadgraph", git = "https://github.com/HakanSeven12/opencadgraph.git", rev = "d3558bb" } dwg-thumbnailer = { path = "crates/dwg-thumbnailer" } flate2 = "1" image = { version = "0.25", default-features = false, features = ["png", "jpeg", "bmp", "tiff"] } diff --git a/crates/ocs_plugin_api/Cargo.toml b/crates/ocs_plugin_api/Cargo.toml index 2ff186185..6667920d1 100644 --- a/crates/ocs_plugin_api/Cargo.toml +++ b/crates/ocs_plugin_api/Cargo.toml @@ -15,7 +15,7 @@ serde_json = { version = "1", optional = true } # Pulled in only by the `host` feature, which adds the `opencadcodec`-typed # `HostApi` runtime surface. The default crate stays dependency-free so engine # crates and external tooling can depend on the manifest/ribbon contract cheaply. -codec = { package = "opencadcodec", git = "https://github.com/HakanSeven12/opencadcodec.git", rev = "c9ffcac", optional = true, features = ["serde"] } +codec = { package = "opencadcodec", git = "https://github.com/HakanSeven12/opencadcodec.git", rev = "8189f83", optional = true, features = ["serde"] } # Runtime IPC and serialization (host feature only). interprocess = { version = "2", optional = true } @@ -39,7 +39,7 @@ serde_json = "1" serde = { version = "1", features = ["derive"] } cargo-lock = "11" # opencadcodec is scanned at build time to generate the embedded type registry. -codec = { package = "opencadcodec", git = "https://github.com/HakanSeven12/opencadcodec.git", rev = "c9ffcac", features = ["serde"] } +codec = { package = "opencadcodec", git = "https://github.com/HakanSeven12/opencadcodec.git", rev = "8189f83", features = ["serde"] } [dev-dependencies] serde_json = "1" diff --git a/crates/ocs_web_worker/Cargo.toml b/crates/ocs_web_worker/Cargo.toml index 00e7bbd79..d643bd257 100644 --- a/crates/ocs_web_worker/Cargo.toml +++ b/crates/ocs_web_worker/Cargo.toml @@ -8,7 +8,7 @@ publish = false crate-type = ["cdylib"] [dependencies] -codec = { package = "opencadcodec", git = "https://github.com/HakanSeven12/opencadcodec.git", rev = "c9ffcac", features = ["serde"] } +codec = { package = "opencadcodec", git = "https://github.com/HakanSeven12/opencadcodec.git", rev = "8189f83", features = ["serde"] } bincode = "1.3" serde = { version = "1", features = ["derive"] } console_error_panic_hook = "0.1" diff --git a/locales/ar-SA/opencadstudio.ftl b/locales/ar-SA/opencadstudio.ftl index 3fa33ea45..8aedf067d 100644 --- a/locales/ar-SA/opencadstudio.ftl +++ b/locales/ar-SA/opencadstudio.ftl @@ -2521,6 +2521,12 @@ inquiry = .id-specify-point = ID حدد نقطة: .list-no-entities-selected-select-entities-firs = LIST: لم تُحدد كيانات. حدد الكيانات أولًا. .massprop-no-entities-selected-select-entities = MASSPROP: لم تُحدد كيانات. حدد الكيانات أولًا. + .massprop-has-no-closed-body-to-measure = MASSPROP: __ocs_fmt_0__ لا يحتوي على جسم مغلق لقياسه. + .volume-4-centroid-4-4-4 = __ocs_fmt_0__ الحجم=__ocs_fmt_1__ مركز الثقل=(__ocs_fmt_2__,__ocs_fmt_3__,__ocs_fmt_4__) + .moments-of-inertia-x-4-y-4-z-4 = عزوم القصور الذاتي X=__ocs_fmt_0__ Y=__ocs_fmt_1__ Z=__ocs_fmt_2__ + .products-of-inertia-xy-4-yz-4-zx-4 = جداءات القصور الذاتي XY=__ocs_fmt_0__ YZ=__ocs_fmt_1__ ZX=__ocs_fmt_2__ + .radii-of-gyration-x-4-y-4-z-4 = أنصاف أقطار الدوران X=__ocs_fmt_0__ Y=__ocs_fmt_1__ Z=__ocs_fmt_2__ + .principal-moments-about-centroid-i-4-j-4-k-4 = العزوم الرئيسية حول مركز الثقل I=__ocs_fmt_0__ J=__ocs_fmt_1__ K=__ocs_fmt_2__ .measure-select-object-to-measure = MEASURE حدد الكائن المراد قياسه: .measure-specify-segment-length = MEASURE حدد طول المقطع: .measuregeom-enter-an-option-distance-radius-an = MEASUREGEOM أدخل خيارًا [مسافة/نصف قطر/زاوية/مساحة]: diff --git a/locales/bg-BG/opencadstudio.ftl b/locales/bg-BG/opencadstudio.ftl index d186cba66..69c6c9f27 100644 --- a/locales/bg-BG/opencadstudio.ftl +++ b/locales/bg-BG/opencadstudio.ftl @@ -2508,6 +2508,12 @@ inquiry = .id-specify-point = ID Посочи точка: .list-no-entities-selected-select-entities-firs = LIST: не са избрани обекти. Първо избери обекти. .massprop-no-entities-selected-select-entities = MASSPROP: не са избрани обекти. Първо избери обекти. + .massprop-has-no-closed-body-to-measure = MASSPROP: __ocs_fmt_0__ няма затворено тяло за измерване. + .volume-4-centroid-4-4-4 = __ocs_fmt_0__ Обем=__ocs_fmt_1__ Център на тежестта=(__ocs_fmt_2__,__ocs_fmt_3__,__ocs_fmt_4__) + .moments-of-inertia-x-4-y-4-z-4 = Инерционни моменти X=__ocs_fmt_0__ Y=__ocs_fmt_1__ Z=__ocs_fmt_2__ + .products-of-inertia-xy-4-yz-4-zx-4 = Центробежни моменти XY=__ocs_fmt_0__ YZ=__ocs_fmt_1__ ZX=__ocs_fmt_2__ + .radii-of-gyration-x-4-y-4-z-4 = Радиуси на инерция X=__ocs_fmt_0__ Y=__ocs_fmt_1__ Z=__ocs_fmt_2__ + .principal-moments-about-centroid-i-4-j-4-k-4 = Главни моменти спрямо центъра на тежестта I=__ocs_fmt_0__ J=__ocs_fmt_1__ K=__ocs_fmt_2__ .measure-select-object-to-measure = MEASURE Избери обект за измерване: .measure-specify-segment-length = MEASURE Посочи дължина на сегмент: .measuregeom-enter-an-option-distance-radius-an = MEASUREGEOM Въведи опция [Разстояние/Радиус/Ъгъл/Площ]: diff --git a/locales/cs-CZ/opencadstudio.ftl b/locales/cs-CZ/opencadstudio.ftl index 07669d6b8..94e44eb2b 100644 --- a/locales/cs-CZ/opencadstudio.ftl +++ b/locales/cs-CZ/opencadstudio.ftl @@ -2508,6 +2508,12 @@ inquiry = .id-specify-point = ID Určete bod: .list-no-entities-selected-select-entities-firs = LIST: nebyly vybrány žádné entity. Nejprve vyberte entity. .massprop-no-entities-selected-select-entities = MASSPROP: nebyly vybrány žádné entity. Nejprve vyberte entity. + .massprop-has-no-closed-body-to-measure = MASSPROP: __ocs_fmt_0__ nemá žádné uzavřené těleso k měření. + .volume-4-centroid-4-4-4 = __ocs_fmt_0__ Objem=__ocs_fmt_1__ Těžiště=(__ocs_fmt_2__,__ocs_fmt_3__,__ocs_fmt_4__) + .moments-of-inertia-x-4-y-4-z-4 = Momenty setrvačnosti X=__ocs_fmt_0__ Y=__ocs_fmt_1__ Z=__ocs_fmt_2__ + .products-of-inertia-xy-4-yz-4-zx-4 = Deviační momenty XY=__ocs_fmt_0__ YZ=__ocs_fmt_1__ ZX=__ocs_fmt_2__ + .radii-of-gyration-x-4-y-4-z-4 = Poloměry setrvačnosti X=__ocs_fmt_0__ Y=__ocs_fmt_1__ Z=__ocs_fmt_2__ + .principal-moments-about-centroid-i-4-j-4-k-4 = Hlavní momenty k těžišti I=__ocs_fmt_0__ J=__ocs_fmt_1__ K=__ocs_fmt_2__ .measure-select-object-to-measure = MEASURE Vyberte objekt k měření: .measure-specify-segment-length = MEASURE Zadejte délku segmentu: .measuregeom-enter-an-option-distance-radius-an = MEASUREGEOM Enter možnost [Vzdálenost/Poloměr/Úhel/Area]: diff --git a/locales/de-DE/opencadstudio.ftl b/locales/de-DE/opencadstudio.ftl index ea5b01467..44e38097d 100644 --- a/locales/de-DE/opencadstudio.ftl +++ b/locales/de-DE/opencadstudio.ftl @@ -2509,6 +2509,12 @@ inquiry = .id-specify-point = ID Anzugeben ist: .list-no-entities-selected-select-entities-firs = LIST: keine Objekte ausgewählt. .massprop-no-entities-selected-select-entities = MASSPROP: Keine Objekte ausgewählt. + .massprop-has-no-closed-body-to-measure = MASSPROP: __ocs_fmt_0__ hat keinen geschlossenen Körper zum Messen. + .volume-4-centroid-4-4-4 = __ocs_fmt_0__ Volumen=__ocs_fmt_1__ Schwerpunkt=(__ocs_fmt_2__,__ocs_fmt_3__,__ocs_fmt_4__) + .moments-of-inertia-x-4-y-4-z-4 = Trägheitsmomente X=__ocs_fmt_0__ Y=__ocs_fmt_1__ Z=__ocs_fmt_2__ + .products-of-inertia-xy-4-yz-4-zx-4 = Deviationsmomente XY=__ocs_fmt_0__ YZ=__ocs_fmt_1__ ZX=__ocs_fmt_2__ + .radii-of-gyration-x-4-y-4-z-4 = Trägheitsradien X=__ocs_fmt_0__ Y=__ocs_fmt_1__ Z=__ocs_fmt_2__ + .principal-moments-about-centroid-i-4-j-4-k-4 = Hauptträgheitsmomente um den Schwerpunkt I=__ocs_fmt_0__ J=__ocs_fmt_1__ K=__ocs_fmt_2__ .measure-select-object-to-measure = MEASURE Objekt auswählen, um zu messen: .measure-specify-segment-length = MEASURE Segmentlänge angeben: .measuregeom-enter-an-option-distance-radius-an = MEASUREGEOM Geben Sie eine Option ein [Distance/Radius/Angle/ARea]: diff --git a/locales/el-GR/opencadstudio.ftl b/locales/el-GR/opencadstudio.ftl index 743e2bb7c..1eb4b91ab 100644 --- a/locales/el-GR/opencadstudio.ftl +++ b/locales/el-GR/opencadstudio.ftl @@ -2508,6 +2508,12 @@ inquiry = .id-specify-point = ID Ορίστε σημείο: .list-no-entities-selected-select-entities-firs = LIST: δεν έχουν επιλεγεί οντότητες. Επιλέξτε πρώτα οντότητες. .massprop-no-entities-selected-select-entities = MASSPROP: δεν έχουν επιλεγεί οντότητες. Επιλέξτε πρώτα οντότητες. + .massprop-has-no-closed-body-to-measure = MASSPROP: __ocs_fmt_0__ δεν έχει κλειστό σώμα για μέτρηση. + .volume-4-centroid-4-4-4 = __ocs_fmt_0__ Όγκος=__ocs_fmt_1__ Κέντρο βάρους=(__ocs_fmt_2__,__ocs_fmt_3__,__ocs_fmt_4__) + .moments-of-inertia-x-4-y-4-z-4 = Ροπές αδράνειας X=__ocs_fmt_0__ Y=__ocs_fmt_1__ Z=__ocs_fmt_2__ + .products-of-inertia-xy-4-yz-4-zx-4 = Γινόμενα αδράνειας XY=__ocs_fmt_0__ YZ=__ocs_fmt_1__ ZX=__ocs_fmt_2__ + .radii-of-gyration-x-4-y-4-z-4 = Ακτίνες αδράνειας X=__ocs_fmt_0__ Y=__ocs_fmt_1__ Z=__ocs_fmt_2__ + .principal-moments-about-centroid-i-4-j-4-k-4 = Κύριες ροπές ως προς το κέντρο βάρους I=__ocs_fmt_0__ J=__ocs_fmt_1__ K=__ocs_fmt_2__ .measure-select-object-to-measure = MEASURE Επιλέξτε αντικείμενο προς μέτρηση: .measure-specify-segment-length = MEASURE Ορίστε μήκος τμήματος: .measuregeom-enter-an-option-distance-radius-an = MEASUREGEOM Δώστε επιλογή [Απόσταση/Ακτίνα/Γωνία/Εμβαδόν]: diff --git a/locales/en-US/opencadstudio.ftl b/locales/en-US/opencadstudio.ftl index 7c22d658b..377caf653 100644 --- a/locales/en-US/opencadstudio.ftl +++ b/locales/en-US/opencadstudio.ftl @@ -2509,6 +2509,12 @@ inquiry = .id-specify-point = ID Specify point: .list-no-entities-selected-select-entities-firs = LIST: no entities selected. Select entities first. .massprop-no-entities-selected-select-entities = MASSPROP: no entities selected. Select entities first. + .massprop-has-no-closed-body-to-measure = MASSPROP: __ocs_fmt_0__ has no closed body to measure. + .volume-4-centroid-4-4-4 = __ocs_fmt_0__ Volume=__ocs_fmt_1__ Centroid=(__ocs_fmt_2__,__ocs_fmt_3__,__ocs_fmt_4__) + .moments-of-inertia-x-4-y-4-z-4 = Moments of inertia X=__ocs_fmt_0__ Y=__ocs_fmt_1__ Z=__ocs_fmt_2__ + .products-of-inertia-xy-4-yz-4-zx-4 = Products of inertia XY=__ocs_fmt_0__ YZ=__ocs_fmt_1__ ZX=__ocs_fmt_2__ + .radii-of-gyration-x-4-y-4-z-4 = Radii of gyration X=__ocs_fmt_0__ Y=__ocs_fmt_1__ Z=__ocs_fmt_2__ + .principal-moments-about-centroid-i-4-j-4-k-4 = Principal moments about centroid I=__ocs_fmt_0__ J=__ocs_fmt_1__ K=__ocs_fmt_2__ .measure-select-object-to-measure = MEASURE Select object to measure: .measure-specify-segment-length = MEASURE Specify segment length: .measuregeom-enter-an-option-distance-radius-an = MEASUREGEOM Enter an option [Distance/Radius/Angle/ARea]: diff --git a/locales/es-ES/opencadstudio.ftl b/locales/es-ES/opencadstudio.ftl index 66d5e31d7..c3b82398b 100644 --- a/locales/es-ES/opencadstudio.ftl +++ b/locales/es-ES/opencadstudio.ftl @@ -2509,6 +2509,12 @@ inquiry = .id-specify-point = ID Especifique un punto: .list-no-entities-selected-select-entities-firs = LIST: no hay entidades seleccionadas. Seleccione primero las entidades. .massprop-no-entities-selected-select-entities = MASSPROP: no hay entidades seleccionadas. Seleccione primero las entidades. + .massprop-has-no-closed-body-to-measure = MASSPROP: __ocs_fmt_0__ no tiene un cuerpo cerrado que medir. + .volume-4-centroid-4-4-4 = __ocs_fmt_0__ Volumen=__ocs_fmt_1__ Centroide=(__ocs_fmt_2__,__ocs_fmt_3__,__ocs_fmt_4__) + .moments-of-inertia-x-4-y-4-z-4 = Momentos de inercia X=__ocs_fmt_0__ Y=__ocs_fmt_1__ Z=__ocs_fmt_2__ + .products-of-inertia-xy-4-yz-4-zx-4 = Productos de inercia XY=__ocs_fmt_0__ YZ=__ocs_fmt_1__ ZX=__ocs_fmt_2__ + .radii-of-gyration-x-4-y-4-z-4 = Radios de giro X=__ocs_fmt_0__ Y=__ocs_fmt_1__ Z=__ocs_fmt_2__ + .principal-moments-about-centroid-i-4-j-4-k-4 = Momentos principales respecto al centroide I=__ocs_fmt_0__ J=__ocs_fmt_1__ K=__ocs_fmt_2__ .measure-select-object-to-measure = MEASURE Seleccione el objeto que desea medir: .measure-specify-segment-length = MEASURE Especifique la longitud del segmento: .measuregeom-enter-an-option-distance-radius-an = MEASUREGEOM Introduzca una opción [Distancia/Radio/Ángulo/Área]: diff --git a/locales/fi-FI/opencadstudio.ftl b/locales/fi-FI/opencadstudio.ftl index fb4ce630b..6503a7115 100644 --- a/locales/fi-FI/opencadstudio.ftl +++ b/locales/fi-FI/opencadstudio.ftl @@ -2508,6 +2508,12 @@ inquiry = .id-specify-point = ID Määritä piste: .list-no-entities-selected-select-entities-firs = LIST: entiteettejä ei ole valittu. Valitse ensin entiteetit. .massprop-no-entities-selected-select-entities = MASSPROP: entiteettejä ei ole valittu. Valitse ensin entiteetit. + .massprop-has-no-closed-body-to-measure = MASSPROP: __ocs_fmt_0__ ei sisällä suljettua kappaletta mitattavaksi. + .volume-4-centroid-4-4-4 = __ocs_fmt_0__ Tilavuus=__ocs_fmt_1__ Painopiste=(__ocs_fmt_2__,__ocs_fmt_3__,__ocs_fmt_4__) + .moments-of-inertia-x-4-y-4-z-4 = Hitausmomentit X=__ocs_fmt_0__ Y=__ocs_fmt_1__ Z=__ocs_fmt_2__ + .products-of-inertia-xy-4-yz-4-zx-4 = Tulohitausmomentit XY=__ocs_fmt_0__ YZ=__ocs_fmt_1__ ZX=__ocs_fmt_2__ + .radii-of-gyration-x-4-y-4-z-4 = Hitaussäteet X=__ocs_fmt_0__ Y=__ocs_fmt_1__ Z=__ocs_fmt_2__ + .principal-moments-about-centroid-i-4-j-4-k-4 = Päähitausmomentit painopisteen suhteen I=__ocs_fmt_0__ J=__ocs_fmt_1__ K=__ocs_fmt_2__ .measure-select-object-to-measure = MEASURE Valitse mitattava kohde: .measure-specify-segment-length = MEASURE Määritä segmentin pituus: .measuregeom-enter-an-option-distance-radius-an = MEASUREGEOM Enter vaihtoehto [etäisyys/säde/kulma/pinta-ala]: diff --git a/locales/fr-FR/opencadstudio.ftl b/locales/fr-FR/opencadstudio.ftl index 85bf5e706..df694d068 100644 --- a/locales/fr-FR/opencadstudio.ftl +++ b/locales/fr-FR/opencadstudio.ftl @@ -2509,6 +2509,12 @@ inquiry = .id-specify-point = ID Spécifier le point: .list-no-entities-selected-select-entities-firs = LIST : aucune entité sélectionnée. Sélectionnez d'abord les entités. .massprop-no-entities-selected-select-entities = MASSPROP : aucune entité sélectionnée. Sélectionnez d'abord les entités. + .massprop-has-no-closed-body-to-measure = MASSPROP: __ocs_fmt_0__ n'a aucun corps fermé à mesurer. + .volume-4-centroid-4-4-4 = __ocs_fmt_0__ Volume=__ocs_fmt_1__ Centre de gravité=(__ocs_fmt_2__,__ocs_fmt_3__,__ocs_fmt_4__) + .moments-of-inertia-x-4-y-4-z-4 = Moments d'inertie X=__ocs_fmt_0__ Y=__ocs_fmt_1__ Z=__ocs_fmt_2__ + .products-of-inertia-xy-4-yz-4-zx-4 = Produits d'inertie XY=__ocs_fmt_0__ YZ=__ocs_fmt_1__ ZX=__ocs_fmt_2__ + .radii-of-gyration-x-4-y-4-z-4 = Rayons de giration X=__ocs_fmt_0__ Y=__ocs_fmt_1__ Z=__ocs_fmt_2__ + .principal-moments-about-centroid-i-4-j-4-k-4 = Moments principaux au centre de gravité I=__ocs_fmt_0__ J=__ocs_fmt_1__ K=__ocs_fmt_2__ .measure-select-object-to-measure = MEASURE Sélectionnez l'objet à mesurer : .measure-specify-segment-length = MEASURE Spécifier la longueur du segment: .measuregeom-enter-an-option-distance-radius-an = MEASUREGEOM Saisissez une option [Distance/Radius/Angle/ARea] : diff --git a/locales/hi-IN/opencadstudio.ftl b/locales/hi-IN/opencadstudio.ftl index 46e2c5f75..fc162ca59 100644 --- a/locales/hi-IN/opencadstudio.ftl +++ b/locales/hi-IN/opencadstudio.ftl @@ -2497,6 +2497,12 @@ inquiry = .id-specify-point = ID निर्दिष्ट बिंदु: .list-no-entities-selected-select-entities-firs = LIST: कोई ऑब्जेक्ट नहीं चुना गया। पहले ऑब्जेक्ट चुनें। .massprop-no-entities-selected-select-entities = MASSPROP: कोई ऑब्जेक्ट नहीं चुना गया। पहले ऑब्जेक्ट चुनें। + .massprop-has-no-closed-body-to-measure = MASSPROP: __ocs_fmt_0__ में मापने के लिए कोई बंद पिंड नहीं है। + .volume-4-centroid-4-4-4 = __ocs_fmt_0__ आयतन=__ocs_fmt_1__ केन्द्रक=(__ocs_fmt_2__,__ocs_fmt_3__,__ocs_fmt_4__) + .moments-of-inertia-x-4-y-4-z-4 = जड़त्व आघूर्ण X=__ocs_fmt_0__ Y=__ocs_fmt_1__ Z=__ocs_fmt_2__ + .products-of-inertia-xy-4-yz-4-zx-4 = जड़त्व गुणनफल XY=__ocs_fmt_0__ YZ=__ocs_fmt_1__ ZX=__ocs_fmt_2__ + .radii-of-gyration-x-4-y-4-z-4 = घूर्णन त्रिज्याएँ X=__ocs_fmt_0__ Y=__ocs_fmt_1__ Z=__ocs_fmt_2__ + .principal-moments-about-centroid-i-4-j-4-k-4 = केन्द्रक के सापेक्ष मुख्य आघूर्ण I=__ocs_fmt_0__ J=__ocs_fmt_1__ K=__ocs_fmt_2__ .measure-select-object-to-measure = MEASURE ऑब्जेक्ट को मापने के लिए चुनें: .measure-specify-segment-length = MEASURE सेगमेंट की लंबाई निर्दिष्ट करें: .measuregeom-enter-an-option-distance-radius-an = MEASUREGEOM विकल्प दर्ज करें [दूरी / त्रिज्या / कोण / क्षेत्रफल]: diff --git a/locales/hu-HU/opencadstudio.ftl b/locales/hu-HU/opencadstudio.ftl index 59b432544..ee0e196ab 100644 --- a/locales/hu-HU/opencadstudio.ftl +++ b/locales/hu-HU/opencadstudio.ftl @@ -2508,6 +2508,12 @@ inquiry = .id-specify-point = ID Pont megadása: .list-no-entities-selected-select-entities-firs = LIST: nincsenek kiválasztva entitások. Először válassza ki az entitásokat. .massprop-no-entities-selected-select-entities = MASSPROP: nincsenek kiválasztva entitások. Először válassza ki az entitásokat. + .massprop-has-no-closed-body-to-measure = MASSPROP: __ocs_fmt_0__ nem tartalmaz mérhető zárt testet. + .volume-4-centroid-4-4-4 = __ocs_fmt_0__ Térfogat=__ocs_fmt_1__ Súlypont=(__ocs_fmt_2__,__ocs_fmt_3__,__ocs_fmt_4__) + .moments-of-inertia-x-4-y-4-z-4 = Tehetetlenségi nyomatékok X=__ocs_fmt_0__ Y=__ocs_fmt_1__ Z=__ocs_fmt_2__ + .products-of-inertia-xy-4-yz-4-zx-4 = Deviációs nyomatékok XY=__ocs_fmt_0__ YZ=__ocs_fmt_1__ ZX=__ocs_fmt_2__ + .radii-of-gyration-x-4-y-4-z-4 = Tehetetlenségi sugarak X=__ocs_fmt_0__ Y=__ocs_fmt_1__ Z=__ocs_fmt_2__ + .principal-moments-about-centroid-i-4-j-4-k-4 = Fő tehetetlenségi nyomatékok a súlypontra I=__ocs_fmt_0__ J=__ocs_fmt_1__ K=__ocs_fmt_2__ .measure-select-object-to-measure = MEASURE Válassza ki a mérendő objektumot: .measure-specify-segment-length = MEASURE Adja meg a szegmens hosszát: .measuregeom-enter-an-option-distance-radius-an = MEASUREGEOM Enter egy opció [Távolság / Sugár / Szög / Terület]: diff --git a/locales/it-IT/opencadstudio.ftl b/locales/it-IT/opencadstudio.ftl index d2bfc1ae1..f4bdd595f 100644 --- a/locales/it-IT/opencadstudio.ftl +++ b/locales/it-IT/opencadstudio.ftl @@ -2508,6 +2508,12 @@ inquiry = .id-specify-point = ID Specificare il punto: .list-no-entities-selected-select-entities-firs = LIST: nessuna entità selezionata. Seleziona prima le entità. .massprop-no-entities-selected-select-entities = MASSPROP: nessuna entità selezionata. Seleziona prima le entità. + .massprop-has-no-closed-body-to-measure = MASSPROP: __ocs_fmt_0__ non ha un corpo chiuso da misurare. + .volume-4-centroid-4-4-4 = __ocs_fmt_0__ Volume=__ocs_fmt_1__ Baricentro=(__ocs_fmt_2__,__ocs_fmt_3__,__ocs_fmt_4__) + .moments-of-inertia-x-4-y-4-z-4 = Momenti d'inerzia X=__ocs_fmt_0__ Y=__ocs_fmt_1__ Z=__ocs_fmt_2__ + .products-of-inertia-xy-4-yz-4-zx-4 = Prodotti d'inerzia XY=__ocs_fmt_0__ YZ=__ocs_fmt_1__ ZX=__ocs_fmt_2__ + .radii-of-gyration-x-4-y-4-z-4 = Raggi di girazione X=__ocs_fmt_0__ Y=__ocs_fmt_1__ Z=__ocs_fmt_2__ + .principal-moments-about-centroid-i-4-j-4-k-4 = Momenti principali rispetto al baricentro I=__ocs_fmt_0__ J=__ocs_fmt_1__ K=__ocs_fmt_2__ .measure-select-object-to-measure = MEASURE Selezionare l'oggetto da misurare: .measure-specify-segment-length = MEASURE Specificare la lunghezza del segmento: .measuregeom-enter-an-option-distance-radius-an = MEASUREGEOM Enter un'opzione [Distanza/Raggio/Angolo/ARea]: diff --git a/locales/ja-JP/opencadstudio.ftl b/locales/ja-JP/opencadstudio.ftl index 72c9b13e0..356c801f5 100644 --- a/locales/ja-JP/opencadstudio.ftl +++ b/locales/ja-JP/opencadstudio.ftl @@ -2499,6 +2499,12 @@ inquiry = .id-specify-point = ID 点を指定: .list-no-entities-selected-select-entities-firs = LIST: 図形が選択されていません。先に選択してください。 .massprop-no-entities-selected-select-entities = MASSPROP: 図形が選択されていません。先に選択してください。 + .massprop-has-no-closed-body-to-measure = MASSPROP: __ocs_fmt_0__ には計測できる閉じたボディがありません。 + .volume-4-centroid-4-4-4 = __ocs_fmt_0__ 体積=__ocs_fmt_1__ 重心=(__ocs_fmt_2__,__ocs_fmt_3__,__ocs_fmt_4__) + .moments-of-inertia-x-4-y-4-z-4 = 慣性モーメント X=__ocs_fmt_0__ Y=__ocs_fmt_1__ Z=__ocs_fmt_2__ + .products-of-inertia-xy-4-yz-4-zx-4 = 慣性乗積 XY=__ocs_fmt_0__ YZ=__ocs_fmt_1__ ZX=__ocs_fmt_2__ + .radii-of-gyration-x-4-y-4-z-4 = 回転半径 X=__ocs_fmt_0__ Y=__ocs_fmt_1__ Z=__ocs_fmt_2__ + .principal-moments-about-centroid-i-4-j-4-k-4 = 重心まわりの主慣性モーメント I=__ocs_fmt_0__ J=__ocs_fmt_1__ K=__ocs_fmt_2__ .measure-select-object-to-measure = MEASURE 計測するオブジェクトを選択: .measure-specify-segment-length = MEASURE 区間長を指定: .measuregeom-enter-an-option-distance-radius-an = MEASUREGEOM オプションを入力 [距離/半径/角度/面積]: diff --git a/locales/ko-KR/opencadstudio.ftl b/locales/ko-KR/opencadstudio.ftl index 403135aa8..07e0d9bd0 100644 --- a/locales/ko-KR/opencadstudio.ftl +++ b/locales/ko-KR/opencadstudio.ftl @@ -2508,6 +2508,12 @@ inquiry = .id-specify-point = ID 지점 지정: .list-no-entities-selected-select-entities-firs = LIST: 선택된 엔터티가 없습니다. 먼저 엔터티를 선택하세요. .massprop-no-entities-selected-select-entities = MASSPROP: 선택된 엔터티가 없습니다. 먼저 엔터티를 선택하세요. + .massprop-has-no-closed-body-to-measure = MASSPROP: __ocs_fmt_0__ 에 측정할 닫힌 바디가 없습니다. + .volume-4-centroid-4-4-4 = __ocs_fmt_0__ 부피=__ocs_fmt_1__ 도심=(__ocs_fmt_2__,__ocs_fmt_3__,__ocs_fmt_4__) + .moments-of-inertia-x-4-y-4-z-4 = 관성 모멘트 X=__ocs_fmt_0__ Y=__ocs_fmt_1__ Z=__ocs_fmt_2__ + .products-of-inertia-xy-4-yz-4-zx-4 = 관성 곱 XY=__ocs_fmt_0__ YZ=__ocs_fmt_1__ ZX=__ocs_fmt_2__ + .radii-of-gyration-x-4-y-4-z-4 = 회전 반경 X=__ocs_fmt_0__ Y=__ocs_fmt_1__ Z=__ocs_fmt_2__ + .principal-moments-about-centroid-i-4-j-4-k-4 = 도심에 대한 주 모멘트 I=__ocs_fmt_0__ J=__ocs_fmt_1__ K=__ocs_fmt_2__ .measure-select-object-to-measure = MEASURE 측정할 물체 선택: .measure-specify-segment-length = MEASURE 세그먼트 길이 지정: .measuregeom-enter-an-option-distance-radius-an = MEASUREGEOM Enter 옵션 [거리/반경/각도/지역]: diff --git a/locales/lo-LA/opencadstudio.ftl b/locales/lo-LA/opencadstudio.ftl index 8b75a109a..a5d212468 100644 --- a/locales/lo-LA/opencadstudio.ftl +++ b/locales/lo-LA/opencadstudio.ftl @@ -2509,6 +2509,12 @@ inquiry = .id-specify-point = ID ກຳນົດຈຸດ: .list-no-entities-selected-select-entities-firs = LIST: ບໍ່ມີອົງປະກອບຖືກເລືອກ. ກະລຸນາເລືອກອົງປະກອບກ່ອນ. .massprop-no-entities-selected-select-entities = MASSPROP: ບໍ່ມີອົງປະກອບຖືກເລືອກ. ກະລຸນາເລືອກອົງປະກອບກ່ອນ. + .massprop-has-no-closed-body-to-measure = MASSPROP: __ocs_fmt_0__ ບໍ່ມີຕົວປິດໃຫ້ວັດແທກ. + .volume-4-centroid-4-4-4 = __ocs_fmt_0__ ປະລິມາດ=__ocs_fmt_1__ ຈຸດສູນກາງມວນ=(__ocs_fmt_2__,__ocs_fmt_3__,__ocs_fmt_4__) + .moments-of-inertia-x-4-y-4-z-4 = ໂມເມັນຄວາມເສື່ອຍ X=__ocs_fmt_0__ Y=__ocs_fmt_1__ Z=__ocs_fmt_2__ + .products-of-inertia-xy-4-yz-4-zx-4 = ຜົນຄູນຄວາມເສື່ອຍ XY=__ocs_fmt_0__ YZ=__ocs_fmt_1__ ZX=__ocs_fmt_2__ + .radii-of-gyration-x-4-y-4-z-4 = ລັດສະໝີການໝູນ X=__ocs_fmt_0__ Y=__ocs_fmt_1__ Z=__ocs_fmt_2__ + .principal-moments-about-centroid-i-4-j-4-k-4 = ໂມເມັນຫຼັກອ້ອມຈຸດສູນກາງມວນ I=__ocs_fmt_0__ J=__ocs_fmt_1__ K=__ocs_fmt_2__ .measure-select-object-to-measure = MEASURE ເລືອກວັດຖຸທີ່ຈະວັດແທກ: .measure-specify-segment-length = MEASURE ກຳນົດຄວາມຍາວຂອງສ່ວນແບ່ງ: .measuregeom-enter-an-option-distance-radius-an = MEASUREGEOM ປ້ອນຕົວເລືອກ [Distance/Radius/Angle/ARea]: diff --git a/locales/nl-NL/opencadstudio.ftl b/locales/nl-NL/opencadstudio.ftl index 112069a59..28e91b02a 100644 --- a/locales/nl-NL/opencadstudio.ftl +++ b/locales/nl-NL/opencadstudio.ftl @@ -2509,6 +2509,12 @@ inquiry = .id-specify-point = ID Specificeer punt: .list-no-entities-selected-select-entities-firs = LIST: geen objecten geselecteerd. Selecteer eerst objecten. .massprop-no-entities-selected-select-entities = MASSPROP: geen objecten geselecteerd. Selecteer eerst objecten. + .massprop-has-no-closed-body-to-measure = MASSPROP: __ocs_fmt_0__ heeft geen gesloten lichaam om te meten. + .volume-4-centroid-4-4-4 = __ocs_fmt_0__ Volume=__ocs_fmt_1__ Zwaartepunt=(__ocs_fmt_2__,__ocs_fmt_3__,__ocs_fmt_4__) + .moments-of-inertia-x-4-y-4-z-4 = Traagheidsmomenten X=__ocs_fmt_0__ Y=__ocs_fmt_1__ Z=__ocs_fmt_2__ + .products-of-inertia-xy-4-yz-4-zx-4 = Deviatiemomenten XY=__ocs_fmt_0__ YZ=__ocs_fmt_1__ ZX=__ocs_fmt_2__ + .radii-of-gyration-x-4-y-4-z-4 = Gyratiestralen X=__ocs_fmt_0__ Y=__ocs_fmt_1__ Z=__ocs_fmt_2__ + .principal-moments-about-centroid-i-4-j-4-k-4 = Hoofdtraagheidsmomenten om het zwaartepunt I=__ocs_fmt_0__ J=__ocs_fmt_1__ K=__ocs_fmt_2__ .measure-select-object-to-measure = MEASURE Selecteer object om mee te meten: .measure-specify-segment-length = MEASURE segmentlengte specificeren: .measuregeom-enter-an-option-distance-radius-an = MEASUREGEOM Voer een optie in [Afstand / Straal / Hoek / Oppervlakte]: diff --git a/locales/pl-PL/opencadstudio.ftl b/locales/pl-PL/opencadstudio.ftl index 16cec2da3..7044544a6 100644 --- a/locales/pl-PL/opencadstudio.ftl +++ b/locales/pl-PL/opencadstudio.ftl @@ -2508,6 +2508,12 @@ inquiry = .id-specify-point = ID Określ punkt: .list-no-entities-selected-select-entities-firs = LIST: nie wybrano żadnych elementów. Najpierw wybierz elementy. .massprop-no-entities-selected-select-entities = MASSPROP: nie wybrano żadnych elementów. Najpierw wybierz elementy. + .massprop-has-no-closed-body-to-measure = MASSPROP: __ocs_fmt_0__ nie ma zamkniętej bryły do zmierzenia. + .volume-4-centroid-4-4-4 = __ocs_fmt_0__ Objętość=__ocs_fmt_1__ Środek ciężkości=(__ocs_fmt_2__,__ocs_fmt_3__,__ocs_fmt_4__) + .moments-of-inertia-x-4-y-4-z-4 = Momenty bezwładności X=__ocs_fmt_0__ Y=__ocs_fmt_1__ Z=__ocs_fmt_2__ + .products-of-inertia-xy-4-yz-4-zx-4 = Momenty dewiacyjne XY=__ocs_fmt_0__ YZ=__ocs_fmt_1__ ZX=__ocs_fmt_2__ + .radii-of-gyration-x-4-y-4-z-4 = Promienie bezwładności X=__ocs_fmt_0__ Y=__ocs_fmt_1__ Z=__ocs_fmt_2__ + .principal-moments-about-centroid-i-4-j-4-k-4 = Główne momenty względem środka ciężkości I=__ocs_fmt_0__ J=__ocs_fmt_1__ K=__ocs_fmt_2__ .measure-select-object-to-measure = MEASURE Wybierz obiekt do pomiaru: .measure-specify-segment-length = MEASURE Określ długość segmentu: .measuregeom-enter-an-option-distance-radius-an = MEASUREGEOM Enter opcja [Odległość/Promień/Kąt/Powierzchnia]: diff --git a/locales/pt-BR/opencadstudio.ftl b/locales/pt-BR/opencadstudio.ftl index e32d1d614..7a8e2ad56 100644 --- a/locales/pt-BR/opencadstudio.ftl +++ b/locales/pt-BR/opencadstudio.ftl @@ -2509,6 +2509,12 @@ inquiry = .id-specify-point = ID Especifique o ponto: .list-no-entities-selected-select-entities-firs = LIST: nenhuma entidade selecionada. Selecione primeiro as entidades. .massprop-no-entities-selected-select-entities = MASSPROP: nenhuma entidade selecionada. Selecione primeiro as entidades. + .massprop-has-no-closed-body-to-measure = MASSPROP: __ocs_fmt_0__ não tem um corpo fechado para medir. + .volume-4-centroid-4-4-4 = __ocs_fmt_0__ Volume=__ocs_fmt_1__ Centroide=(__ocs_fmt_2__,__ocs_fmt_3__,__ocs_fmt_4__) + .moments-of-inertia-x-4-y-4-z-4 = Momentos de inércia X=__ocs_fmt_0__ Y=__ocs_fmt_1__ Z=__ocs_fmt_2__ + .products-of-inertia-xy-4-yz-4-zx-4 = Produtos de inércia XY=__ocs_fmt_0__ YZ=__ocs_fmt_1__ ZX=__ocs_fmt_2__ + .radii-of-gyration-x-4-y-4-z-4 = Raios de giração X=__ocs_fmt_0__ Y=__ocs_fmt_1__ Z=__ocs_fmt_2__ + .principal-moments-about-centroid-i-4-j-4-k-4 = Momentos principais em relação ao centroide I=__ocs_fmt_0__ J=__ocs_fmt_1__ K=__ocs_fmt_2__ .measure-select-object-to-measure = MEASURE Selecione o objeto a medir: .measure-specify-segment-length = MEASURE Especifique o comprimento do segmento: .measuregeom-enter-an-option-distance-radius-an = MEASUREGEOM Insira uma opção [Distância/Raio/Ângulo/ÁRea]: diff --git a/locales/ru-RU/opencadstudio.ftl b/locales/ru-RU/opencadstudio.ftl index 5734d26e5..b078726bd 100644 --- a/locales/ru-RU/opencadstudio.ftl +++ b/locales/ru-RU/opencadstudio.ftl @@ -2512,6 +2512,12 @@ inquiry = .id-specify-point = ID Укажите точку: .list-no-entities-selected-select-entities-firs = LIST: не выбрано ни одного объекта. .massprop-no-entities-selected-select-entities = MASSPROP: не выбрано ни одного объекта. + .massprop-has-no-closed-body-to-measure = MASSPROP: __ocs_fmt_0__ не имеет замкнутого тела для измерения. + .volume-4-centroid-4-4-4 = __ocs_fmt_0__ Объём=__ocs_fmt_1__ Центр масс=(__ocs_fmt_2__,__ocs_fmt_3__,__ocs_fmt_4__) + .moments-of-inertia-x-4-y-4-z-4 = Моменты инерции X=__ocs_fmt_0__ Y=__ocs_fmt_1__ Z=__ocs_fmt_2__ + .products-of-inertia-xy-4-yz-4-zx-4 = Центробежные моменты XY=__ocs_fmt_0__ YZ=__ocs_fmt_1__ ZX=__ocs_fmt_2__ + .radii-of-gyration-x-4-y-4-z-4 = Радиусы инерции X=__ocs_fmt_0__ Y=__ocs_fmt_1__ Z=__ocs_fmt_2__ + .principal-moments-about-centroid-i-4-j-4-k-4 = Главные моменты относительно центра масс I=__ocs_fmt_0__ J=__ocs_fmt_1__ K=__ocs_fmt_2__ .measure-select-object-to-measure = MEASURE Выберите объект для измерения: .measure-specify-segment-length = MEASURE Укажите длину сегмента: .measuregeom-enter-an-option-distance-radius-an = MEASUREGEOM Введите опцию [Расстояние/Радиус/Англия/Арея]: diff --git a/locales/tr-TR/opencadstudio.ftl b/locales/tr-TR/opencadstudio.ftl index 87e53c2af..54a1c9daf 100644 --- a/locales/tr-TR/opencadstudio.ftl +++ b/locales/tr-TR/opencadstudio.ftl @@ -2490,6 +2490,12 @@ inquiry = .id-specify-point = ID Noktayı belirtin: .list-no-entities-selected-select-entities-firs = LIST: Nesne seçilmedi. Önce nesneleri seçin. .massprop-no-entities-selected-select-entities = MASSPROP: Nesne seçilmedi. Önce nesneleri seçin. + .massprop-has-no-closed-body-to-measure = MASSPROP: __ocs_fmt_0__ için ölçülecek kapalı gövde yok. + .volume-4-centroid-4-4-4 = __ocs_fmt_0__ Hacim=__ocs_fmt_1__ Ağırlık merkezi=(__ocs_fmt_2__,__ocs_fmt_3__,__ocs_fmt_4__) + .moments-of-inertia-x-4-y-4-z-4 = Eylemsizlik momentleri X=__ocs_fmt_0__ Y=__ocs_fmt_1__ Z=__ocs_fmt_2__ + .products-of-inertia-xy-4-yz-4-zx-4 = Eylemsizlik çarpımları XY=__ocs_fmt_0__ YZ=__ocs_fmt_1__ ZX=__ocs_fmt_2__ + .radii-of-gyration-x-4-y-4-z-4 = Jirasyon yarıçapları X=__ocs_fmt_0__ Y=__ocs_fmt_1__ Z=__ocs_fmt_2__ + .principal-moments-about-centroid-i-4-j-4-k-4 = Ağırlık merkezine göre asal momentler I=__ocs_fmt_0__ J=__ocs_fmt_1__ K=__ocs_fmt_2__ .measure-select-object-to-measure = MEASURE Ölçülecek nesneyi seçin: .measure-specify-segment-length = MEASURE Parça uzunluğunu belirtin: .measuregeom-enter-an-option-distance-radius-an = MEASUREGEOM Bir seçenek girin [Mesafe/Yarıçap/Açı/Alan]: diff --git a/locales/zh-CN/opencadstudio.ftl b/locales/zh-CN/opencadstudio.ftl index ac1e10a16..5eb0d8315 100644 --- a/locales/zh-CN/opencadstudio.ftl +++ b/locales/zh-CN/opencadstudio.ftl @@ -2496,6 +2496,12 @@ inquiry = .id-specify-point = ID 指定点: .list-no-entities-selected-select-entities-firs = LIST:没有选择实体。首先选择实体。 .massprop-no-entities-selected-select-entities = MASSPROP:没有选择实体。首先选择实体。 + .massprop-has-no-closed-body-to-measure = MASSPROP: __ocs_fmt_0__ 没有可测量的封闭实体。 + .volume-4-centroid-4-4-4 = __ocs_fmt_0__ 体积=__ocs_fmt_1__ 质心=(__ocs_fmt_2__,__ocs_fmt_3__,__ocs_fmt_4__) + .moments-of-inertia-x-4-y-4-z-4 = 惯性矩 X=__ocs_fmt_0__ Y=__ocs_fmt_1__ Z=__ocs_fmt_2__ + .products-of-inertia-xy-4-yz-4-zx-4 = 惯性积 XY=__ocs_fmt_0__ YZ=__ocs_fmt_1__ ZX=__ocs_fmt_2__ + .radii-of-gyration-x-4-y-4-z-4 = 回转半径 X=__ocs_fmt_0__ Y=__ocs_fmt_1__ Z=__ocs_fmt_2__ + .principal-moments-about-centroid-i-4-j-4-k-4 = 关于质心的主力矩 I=__ocs_fmt_0__ J=__ocs_fmt_1__ K=__ocs_fmt_2__ .measure-select-object-to-measure = MEASURE 选择要定距等分的对象: .measure-specify-segment-length = MEASURE 指定线段长度: .measuregeom-enter-an-option-distance-radius-an = MEASUREGEOM 输入选项 [距离/半径/角度/面积]: diff --git a/locales/zh-TW/opencadstudio.ftl b/locales/zh-TW/opencadstudio.ftl index 122cf89e5..40e3fb081 100644 --- a/locales/zh-TW/opencadstudio.ftl +++ b/locales/zh-TW/opencadstudio.ftl @@ -2508,6 +2508,12 @@ inquiry = .id-specify-point = ID 指定點: .list-no-entities-selected-select-entities-firs = LIST:沒有選擇實體。首先選擇實體。 .massprop-no-entities-selected-select-entities = MASSPROP:沒有選擇實體。首先選擇實體。 + .massprop-has-no-closed-body-to-measure = MASSPROP: __ocs_fmt_0__ 沒有可量測的封閉實體。 + .volume-4-centroid-4-4-4 = __ocs_fmt_0__ 體積=__ocs_fmt_1__ 質心=(__ocs_fmt_2__,__ocs_fmt_3__,__ocs_fmt_4__) + .moments-of-inertia-x-4-y-4-z-4 = 慣性矩 X=__ocs_fmt_0__ Y=__ocs_fmt_1__ Z=__ocs_fmt_2__ + .products-of-inertia-xy-4-yz-4-zx-4 = 慣性積 XY=__ocs_fmt_0__ YZ=__ocs_fmt_1__ ZX=__ocs_fmt_2__ + .radii-of-gyration-x-4-y-4-z-4 = 迴轉半徑 X=__ocs_fmt_0__ Y=__ocs_fmt_1__ Z=__ocs_fmt_2__ + .principal-moments-about-centroid-i-4-j-4-k-4 = 關於質心的主力矩 I=__ocs_fmt_0__ J=__ocs_fmt_1__ K=__ocs_fmt_2__ .measure-select-object-to-measure = MEASURE 選擇要定距等分的物件: .measure-specify-segment-length = MEASURE 指定線段長度: .measuregeom-enter-an-option-distance-radius-an = MEASUREGEOM 輸入選項 [距離/半徑/角度/面積]: diff --git a/plugins/opencad-python/Cargo.lock b/plugins/opencad-python/Cargo.lock index 308d68303..e94e40fea 100644 --- a/plugins/opencad-python/Cargo.lock +++ b/plugins/opencad-python/Cargo.lock @@ -1264,7 +1264,7 @@ dependencies = [ [[package]] name = "opencadcodec" version = "0.6.0" -source = "git+https://github.com/HakanSeven12/opencadcodec.git?rev=c9ffcac#c9ffcac5ecdc7a504cc4a7e3ecb52ac9d587c8bf" +source = "git+https://github.com/HakanSeven12/opencadcodec.git?rev=8189f83#8189f833574c544fc57a1d773591014c3a5907c9" dependencies = [ "anyhow", "bitflags", diff --git a/src/app/commands/inquiry.rs b/src/app/commands/inquiry.rs index dda3f01b1..d0a31134b 100644 --- a/src/app/commands/inquiry.rs +++ b/src/app/commands/inquiry.rs @@ -1114,6 +1114,63 @@ impl OpenCADStudio { for (handle, _) in &selected { if let Some(entity) = self.tabs[i].scene.document.get_entity(*handle) { use crate::entities::traits::EntityTypeOps; + // A solid's properties come from its B-rep: exact + // where the kernel knows the shape, a fine mesh + // otherwise — not the display mesh. + let acis = match entity { + codec::EntityType::Solid3D(solid) => Some(&solid.acis_data), + codec::EntityType::Body(body) => Some(&body.acis_data), + _ => None, + }; + if let Some(acis) = acis { + let properties = crate::scene::convert::solid3d_tess::kernel_acis_body(acis) + .and_then(|body| kernel::brep::mass_properties(&body)); + let Some(p) = properties else { + self.command_line.push_error(crate::tf!( + "MASSPROP: {} has no closed body to measure.", + crate::entities::names::dxf_name(entity), + ).as_ref()); + continue; + }; + let [x, y, z] = p.centroid; + let [ix, iy, iz] = p.moment_of_inertia; + let [pxy, pyz, pzx] = p.product_of_inertia; + let [rx, ry, rz] = p.radii_of_gyration; + let [i1, i2, i3] = p.principal_moments; + self.command_line.push_output(crate::tf!( + "{} Volume={:.4} Centroid=({:.4},{:.4},{:.4})", + crate::entities::names::dxf_name(entity), + p.volume, + x, + y, + z, + ).as_ref()); + self.command_line.push_output(crate::tf!( + "Moments of inertia X={:.4} Y={:.4} Z={:.4}", + ix, + iy, + iz, + ).as_ref()); + self.command_line.push_output(crate::tf!( + "Products of inertia XY={:.4} YZ={:.4} ZX={:.4}", + pxy, + pyz, + pzx, + ).as_ref()); + self.command_line.push_output(crate::tf!( + "Radii of gyration X={:.4} Y={:.4} Z={:.4}", + rx, + ry, + rz, + ).as_ref()); + self.command_line.push_output(crate::tf!( + "Principal moments about centroid I={:.4} J={:.4} K={:.4}", + i1, + i2, + i3, + ).as_ref()); + continue; + } if let Some(props) = entity.mass_props() { self.command_line.push_output(crate::tf!( "{} Area={:.4} Perimeter={:.4} Centroid=({:.4},{:.4})", diff --git a/src/locale_catalog.rs b/src/locale_catalog.rs index 19b4ed554..e41c57042 100644 --- a/src/locale_catalog.rs +++ b/src/locale_catalog.rs @@ -1933,6 +1933,12 @@ pub(super) fn message_attribute(source: &str) -> Option<(&'static str, &'static "M density" => Some(("properties", "m-density")), "M vertex count" => Some(("properties", "m-vertex-count")), "MASSPROP: no entities selected. Select entities first." => Some(("inquiry", "massprop-no-entities-selected-select-entities")), + "MASSPROP: {} has no closed body to measure." => Some(("inquiry", "massprop-has-no-closed-body-to-measure")), + "{} Volume={:.4} Centroid=({:.4},{:.4},{:.4})" => Some(("inquiry", "volume-4-centroid-4-4-4")), + "Moments of inertia X={:.4} Y={:.4} Z={:.4}" => Some(("inquiry", "moments-of-inertia-x-4-y-4-z-4")), + "Products of inertia XY={:.4} YZ={:.4} ZX={:.4}" => Some(("inquiry", "products-of-inertia-xy-4-yz-4-zx-4")), + "Radii of gyration X={:.4} Y={:.4} Z={:.4}" => Some(("inquiry", "radii-of-gyration-x-4-y-4-z-4")), + "Principal moments about centroid I={:.4} J={:.4} K={:.4}" => Some(("inquiry", "principal-moments-about-centroid-i-4-j-4-k-4")), "MATCHPROP Select destination objects (Enter to finish):" => Some(("properties", "matchprop-select-destination-objects-enter-to")), "MATCHPROP Select source object:" => Some(("properties", "matchprop-select-source-object")), "MEASURE Select object to measure:" => Some(("inquiry", "measure-select-object-to-measure")), diff --git a/src/modules/draw/modify/fillet.rs b/src/modules/draw/modify/fillet.rs index c36606f7e..f3a6608d4 100644 --- a/src/modules/draw/modify/fillet.rs +++ b/src/modules/draw/modify/fillet.rs @@ -769,6 +769,9 @@ enum FilletEntity { handle: Handle, seg_idx: usize, }, + /// A circle, ellipse or spline: filleted through the kernel's general + /// construction, and trimmed only when it has ends to trim. + Curve(EntityType), } impl FilletEntity { @@ -776,6 +779,9 @@ impl FilletEntity { match e { EntityType::Line(l) => Some(Self::Line(l.clone())), EntityType::Arc(a) => Some(Self::Arc(a.clone())), + EntityType::Circle(_) | EntityType::Ellipse(_) | EntityType::Spline(_) => { + crate::entities::curve::entity_curve_xy(e).map(|_| Self::Curve(e.clone())) + } _ => None, } } @@ -794,6 +800,7 @@ impl FilletEntity { Self::Line(l) => EntityType::Line(l.clone()), Self::Arc(a) => EntityType::Arc(a.clone()), Self::LwPoly { poly, .. } => EntityType::LwPolyline(poly.clone()), + Self::Curve(entity) => entity.clone(), } } @@ -802,6 +809,20 @@ impl FilletEntity { Self::Line(l) => l.start.z, Self::Arc(a) => a.center.z, Self::LwPoly { poly, .. } => poly.elevation, + Self::Curve(EntityType::Circle(c)) => c.center.z, + Self::Curve(EntityType::Ellipse(e)) => e.center.z, + Self::Curve(EntityType::Spline(s)) => s.control_points.first().map_or(0.0, |p| p.z), + Self::Curve(_) => 0.0, + } + } + + /// The shape as a kernel curve in plan. + fn kernel_curve(&self) -> Option { + match self { + Self::Line(l) => Some(line_curve(l)), + Self::Arc(a) => Some(arc_curve(a)), + Self::LwPoly { poly, seg_idx, .. } => Some(line_curve(&lwpoly_seg_as_line(poly, *seg_idx))), + Self::Curve(entity) => crate::entities::curve::entity_curve_xy(entity), } } } @@ -825,6 +846,9 @@ fn compute_fillet_entities( if picks_arc_segment(e1) || picks_arc_segment(e2) { return None; } + if matches!(e1, FilletEntity::Curve(_)) || matches!(e2, FilletEntity::Curve(_)) { + return fillet_curves(e1, click1, e2, click2, radius, z); + } match (e1, e2) { // ── Line × Line ─────────────────────────────────────────────────── @@ -1011,6 +1035,8 @@ fn compute_fillet_entities( None } } + // Answered by `fillet_curves` above. + (FilletEntity::Curve(_), _) | (_, FilletEntity::Curve(_)) => None, } } @@ -1268,6 +1294,116 @@ fn fillet_arc_arc( None } +/// FILLET where one side is a circle, ellipse or spline. The kernel finds the +/// tangent arcs; each side is then cut back to its tangent point, keeping the +/// part that was picked. A closed curve has no end to cut back and is left +/// whole. +fn fillet_curves( + e1: &FilletEntity, + click1: [f64; 2], + e2: &FilletEntity, + click2: [f64; 2], + radius: f64, + z: f64, +) -> Option<(EntityType, EntityType, Option)> { + if radius < 1e-9 { + return None; + } + let (a, b) = (e1.kernel_curve()?, e2.kernel_curve()?); + let common = match e1 { + FilletEntity::Line(l) => l.common.clone(), + FilletEntity::Arc(a) => a.common.clone(), + FilletEntity::LwPoly { poly, .. } => poly.common.clone(), + FilletEntity::Curve(entity) => entity.common().clone(), + }; + for fillet in ranked_fillets(&a, click1, &b, click2, radius) { + let (Some(first), Some(second)) = ( + trim_to_tangent(e1, &a, fillet.tangent1, click1), + trim_to_tangent(e2, &b, fillet.tangent2, click2), + ) else { + continue; + }; + return Some(( + first, + second, + Some(EntityType::Arc(fillet_entity(&fillet, radius, z, &common))), + )); + } + None +} + +/// One side of a fillet cut back to where the arc touches it, the picked part +/// kept. `None` when the touch is off a bounded curve's drawn part — only a +/// line may be extended to meet the arc. +fn trim_to_tangent( + entity: &FilletEntity, + curve: &KernelCurve, + touch: [f64; 2], + click: [f64; 2], +) -> Option { + match entity { + FilletEntity::Line(l) => trim_line_to_point(l, touch, click).map(EntityType::Line), + FilletEntity::LwPoly { poly, seg_idx, .. } => { + let line = lwpoly_seg_as_line(poly, *seg_idx); + let trimmed = trim_line_to_point(&line, touch, click)?; + Some(EntityType::LwPolyline(rebuild_poly_from_trimmed_line(poly, *seg_idx, &line, &trimmed))) + } + FilletEntity::Arc(arc) => { + let (centre, _, start, end, _) = arc_geom(arc); + let at = arc_angle_at(centre, touch); + let clamped = clamp_angle_to_arc(at, start, end); + if (norm_angle(at) - norm_angle(clamped)).abs() > 0.01 { + return None; + } + let picked = clamp_angle_to_arc(arc_angle_at(centre, click), start, end); + Some(EntityType::Arc( + if (clamped - start).rem_euclid(TAU) <= (picked - start).rem_euclid(TAU) { + trim_arc(arc, clamped, end) + } else { + trim_arc(arc, start, clamped) + }, + )) + } + FilletEntity::Curve(source) => { + let at = curve.parameter_at(touch); + let on = curve.point_at(at); + let scale = 1e-6 * (1.0 + touch[0].abs().max(touch[1].abs())); + if (on[0] - touch[0]).hypot(on[1] - touch[1]) > scale.max(1e-6 * curve.length()) { + return None; + } + if curve.is_closed() { + return Some(source.clone()); + } + let keep_end = curve.parameter_at(click) >= at; + match source { + // Its plan image runs the entity's own parameter only when + // it faces up; a mirrored one is left alone. + EntityType::Ellipse(ellipse) if ellipse.normal.z > 0.0 => { + let mut trimmed = ellipse.clone(); + trimmed.common.handle = Handle::NULL; + let sweep = { + let raw = ellipse.end_parameter - ellipse.start_parameter; + if raw <= 0.0 { raw + TAU } else { raw } + }; + let cut = ellipse.start_parameter + at * sweep; + if keep_end { + trimmed.start_parameter = cut; + } else { + trimmed.end_parameter = cut; + } + Some(EntityType::Ellipse(trimmed)) + } + EntityType::Spline(spline) => { + let (low, high) = super::spline_ops::spline_range(spline)?; + let (head, tail) = super::spline_ops::spline_cut(spline, low + at * (high - low))?; + Some(EntityType::Spline(if keep_end { tail } else { head })) + } + _ => None, + } + } + } +} + /// Trim a line endpoint nearest to the intersection point, keeping the click side. fn trim_line_to_point(line: &LineEnt, isect: [f64; 2], click: [f64; 2]) -> Option { let mut l = line.clone(); diff --git a/src/modules/draw/modify/offset.rs b/src/modules/draw/modify/offset.rs index 843c67a11..576cd9460 100644 --- a/src/modules/draw/modify/offset.rs +++ b/src/modules/draw/modify/offset.rs @@ -15,7 +15,6 @@ // offset at once on the cursor's side; a negative one, on the other side. use crate::entities::curve::{entity_curve, lwpolyline_world_xy}; -use crate::modules::draw::modify::spline_ops::spline_sample_xy; use codec::entities::LwVertex; use codec::entities::{ Arc as ArcEnt, Circle as CircleEnt, Ellipse as EllipseEnt, Line as LineEnt, LwPolyline, @@ -24,7 +23,6 @@ use codec::entities::{ use codec::{EntityType, Handle}; // Polyline offsetting, and the angle normalisation that goes with it, come // from the kernel; only the entity conversion stays here. -use kernel::geom2d::nurbs::clamped_uniform_knots; use kernel::geom2d::{ offset_polyline, Polyline as KernelPolyline, PolylineVertex as KernelVertex, }; @@ -205,111 +203,77 @@ fn offset_lwpolyline(p: &LwPolyline, dist: f64, side_pt: Vec3) -> Option Option { - let a = (e.major_axis.x.powi(2) + e.major_axis.y.powi(2)).sqrt(); - if a < 1e-9 { - return None; - } - let b = a * e.minor_axis_ratio; - let nx = e.major_axis.x / a; - let ny = e.major_axis.y / a; - // Project side_pt onto ellipse local frame and test inside/outside. - let rx = side_pt.x as f64 - e.center.x; - let ry = side_pt.y as f64 - e.center.y; - let xl = rx * nx + ry * ny; - let yl = -rx * ny + ry * nx; - let inside = (xl / a).powi(2) + (yl / b).powi(2) < 1.0; - let sign = if inside { -1.0 } else { 1.0 }; - - let new_a = a + sign * dist; - let new_b = b + sign * dist; - if new_a <= 1e-9 || new_b <= 1e-9 { - return None; - } - - let mut new_e = e.clone(); - new_e.common.handle = Handle::NULL; - // Scale the major_axis vector proportionally. - let scale = new_a / a; - new_e.major_axis.x *= scale; - new_e.major_axis.y *= scale; - new_e.major_axis.z *= scale; - new_e.minor_axis_ratio = new_b / new_a; - Some(EntityType::Ellipse(new_e)) + let source = EntityType::Ellipse(e.clone()); + let mut template = SplineEnt::new(); + template.common = e.common.clone(); + offset_curved(&source, template, dist, side_pt) } -// ── Spline offset ────────────────────────────────────────────────────────── -// -// Strategy: sample the spline into N points, offset each sample point by -// `dist` along the local perpendicular (based on the finite-difference -// tangent), then fit a new spline through the offset points. - fn offset_spline(spl: &SplineEnt, dist: f64, side_pt: Vec3) -> Option { - let (ts_knot, pts) = spline_sample_xy(spl, 64); - let n = pts.len(); - if n < 2 { + offset_curved(&EntityType::Spline(spl.clone()), spl.clone(), dist, side_pt) +} + +fn offset_curved( + source: &EntityType, + mut template: SplineEnt, + dist: f64, + side_pt: Vec3, +) -> Option { + let planar = entity_curve(source)?; + let side = planar + .plane + .project([side_pt.x as f64, side_pt.y as f64, side_pt.z as f64])?; + // Left of the curve's direction of travel is the kernel's positive side. + let curve = &planar.curve; + let at = curve.parameter_at(side); + let step = 1e-6; + let (before, after) = if curve.is_closed() { + (curve.point_at((at - step).rem_euclid(1.0)), curve.point_at((at + step).rem_euclid(1.0))) + } else { + (curve.point_at((at - step).max(0.0)), curve.point_at((at + step).min(1.0))) + }; + let foot = curve.point_at(at); + let along = [after[0] - before[0], after[1] - before[1]]; + let toward = [side[0] - foot[0], side[1] - foot[1]]; + let left = along[0] * toward[1] - along[1] * toward[0] > 0.0; + let signed = if left { dist.abs() } else { -dist.abs() }; + let tolerance = (curve.length() * 1e-6).max(1e-9); + let kernel::geom2d::Curve::Nurbs(parallel) = + kernel::geom2d::offset_curve(curve, signed, tolerance)? + else { return None; - } - - // Determine offset sign from the first non-degenerate tangent. - let sign: f64 = (0..n - 1).find_map(|i| { - let dx = pts[i + 1][0] - pts[i][0]; - let dy = pts[i + 1][1] - pts[i][1]; - let len = (dx * dx + dy * dy).sqrt(); - if len < 1e-12 { - return None; - } - let vx = side_pt.x as f64 - pts[i][0]; - let vy = side_pt.y as f64 - pts[i][1]; - let cross = dx * vy - dy * vx; - Some(if cross >= 0.0 { 1.0 } else { -1.0 }) - })?; - - // Offset each sample point along the local normal. - let offset_pts: Vec = pts + }; + template.common.handle = Handle::NULL; + template.degree = parallel.degree() as i32; + template.knots = parallel.knots().to_vec(); + template.control_points = parallel + .control_points() .iter() - .enumerate() - .map(|(i, p)| { - // Tangent via central / forward / backward difference. - let (dx, dy) = if i == 0 { - let d = [pts[1][0] - pts[0][0], pts[1][1] - pts[0][1]]; - (d[0], d[1]) - } else if i == n - 1 { - let d = [pts[n - 1][0] - pts[n - 2][0], pts[n - 1][1] - pts[n - 2][1]]; - (d[0], d[1]) - } else { - ( - (pts[i + 1][0] - pts[i - 1][0]) * 0.5, - (pts[i + 1][1] - pts[i - 1][1]) * 0.5, - ) - }; - let len = (dx * dx + dy * dy).sqrt().max(1e-12); - let nx = -dy / len; // left perpendicular - let ny = dx / len; - let z = spl.control_points.first().map(|v| v.z).unwrap_or(0.0); - codec::types::Vector3::new(p[0] + sign * nx * dist, p[1] + sign * ny * dist, z) + .map(|uv| { + let [x, y, z] = planar.plane.point_at(*uv); + codec::types::Vector3::new(x, y, z) }) .collect(); - - let _ = ts_knot; - // Build a new spline from the offset control points (treat sample pts as fit pts → ctrl pts). - let degree = spl.degree.max(1) as usize; - let new_ctrl: Vec = offset_pts; - let n_ctrl = new_ctrl.len(); - let mut new_spl = spl.clone(); - new_spl.common.handle = Handle::NULL; - new_spl.control_points = new_ctrl; - new_spl.knots = clamped_uniform_knots(degree, n_ctrl); - new_spl.fit_points.clear(); - new_spl.weights.clear(); - Some(EntityType::Spline(new_spl)) + template.weights = if parallel.is_rational() { parallel.weights().to_vec() } else { Vec::new() }; + template.flags.rational = parallel.is_rational(); + template.flags.periodic = false; + template.flags.closed = curve.is_closed(); + if let Some([x, y, z]) = planar.plane.normal() { + template.normal = codec::types::Vector3::new(x, y, z); + } + // A parallel is no longer the curve through the source's fit points. + template.fit_points.clear(); + template.begin_tangent = codec::types::Vector3::new(0.0, 0.0, 0.0); + template.end_tangent = codec::types::Vector3::new(0.0, 0.0, 0.0); + Some(EntityType::Spline(template)) } // ── Dispatch ───────────────────────────────────────────────────────────────