diff --git a/localization/i18n/OrcaSlicer.pot b/localization/i18n/OrcaSlicer.pot index 7d341365c5..46d08da724 100644 --- a/localization/i18n/OrcaSlicer.pot +++ b/localization/i18n/OrcaSlicer.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-01-13 17:34+0100\n" +"POT-Creation-Date: 2024-01-19 18:27+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -3758,7 +3758,7 @@ msgstr "" msgid "Size:" msgstr "" -#, possible-c-format, possible-boost-format +#, possible-boost-format msgid "" "Conflicts of gcode paths have been found at layer %d, z = %.2lf mm. Please " "separate the conflicted objects farther (%s <-> %s)." @@ -3830,6 +3830,15 @@ msgstr "" msgid "Resolution" msgstr "" +msgid "Enable" +msgstr "" + +msgid "Hostname or IP" +msgstr "" + +msgid "Custom camera source" +msgstr "" + msgid "Show \"Live Video\" guide page." msgstr "" @@ -4605,6 +4614,9 @@ msgstr "" msgid "Camera Setting" msgstr "" +msgid "Switch Camera View" +msgstr "" + msgid "Control" msgstr "" @@ -8126,6 +8138,29 @@ msgid "" "bottom shell layers" msgstr "" +msgid "Apply gap fill" +msgstr "" + +msgid "" +"Enables gap fill for the selected surfaces. The minimum gap length that will " +"be filled can be controlled from the filter out tiny gaps option below.\n" +"\n" +"Options:\n" +"1. Everywhere: Applies gap fill to top, bottom and internal solid surfaces\n" +"2. Top and Bottom surfaces: Applies gap fill to top and bottom surfaces " +"only\n" +"3. Nowhere: Disables gap fill\n" +msgstr "" + +msgid "Everywhere" +msgstr "" + +msgid "Top and bottom surfaces" +msgstr "" + +msgid "Nowhere" +msgstr "" + msgid "Force cooling for overhang and bridge" msgstr "" @@ -8562,6 +8597,18 @@ msgid "" "thickness (top+bottom solid layers)" msgstr "" +msgid "Further reduce solid infill on walls (experimental)" +msgstr "" + +msgid "" +"Further reduces any solid infill applied to walls. As there will be very " +"limited infill supporting solid surfaces, make sure that you are using " +"adequate number of walls to support the part on sloping surfaces.\n" +"\n" +"For heavily sloped surfaces this option is not suitable as it will generate " +"too thin of a top layer and should be disabled." +msgstr "" + msgid "Top surface pattern" msgstr "" @@ -9840,9 +9887,6 @@ msgid "" "model and save printing time, but make slicing and G-code generating slower" msgstr "" -msgid "Enable" -msgstr "" - msgid "Filename format" msgstr "" @@ -12557,3 +12601,151 @@ msgid "" "Message body: \"%1%\"\n" "Error: \"%2%\"" msgstr "" + +#: resources/data/hints.ini: [hint:Precise wall] +msgid "Precise wall\nDid you know that turning on precise wall can improve precision and layer consistency?" +msgstr "" + +#: resources/data/hints.ini: [hint:Sandwich mode] +msgid "Sandwich mode\nDid you know that you can use sandwich mode (inner-outer-inner) to improve precision and layer consistency if your model doesn't have very steep overhangs?" +msgstr "" + +#: resources/data/hints.ini: [hint:Chamber temperature] +msgid "Chamber temperature\nDid you know that OrcaSlicer supports chamber temperature?" +msgstr "" + +#: resources/data/hints.ini: [hint:Calibration] +msgid "Calibration\nDid you know that calibrating your printer can do wonders? Check out our beloved calibration solution in OrcaSlicer." +msgstr "" + +#: resources/data/hints.ini: [hint:Auxiliary fan] +msgid "Auxiliary fan\nDid you know that OrcaSlicer supports Auxiliary part cooling fan?" +msgstr "" + +#: resources/data/hints.ini: [hint:Air filtration] +msgid "Air filtration/Exhuast Fan\nDid you know that OrcaSlicer can support Air filtration/Exhuast Fan?" +msgstr "" + +#: resources/data/hints.ini: [hint:G-code window] +msgid "G-code window\nYou can turn on/off the G-code window by pressing the C key." +msgstr "" + +#: resources/data/hints.ini: [hint:Switch workspaces] +msgid "Switch workspaces\nYou can switch between Prepare and Preview workspaces by pressing the Tab key." +msgstr "" + +#: resources/data/hints.ini: [hint:How to use keyboard shortcuts] +msgid "How to use keyboard shortcuts\nDid you know that Orca Slicer offers a wide range of keyboard shortcuts and 3D scene operations." +msgstr "" + +#: resources/data/hints.ini: [hint:Reverse on odd] +msgid "Reverse on odd\nDid you know that Reverse on odd feature can significantly improve the surface quality of your overhangs?" +msgstr "" + +#: resources/data/hints.ini: [hint:Cut Tool] +msgid "Cut Tool\nDid you know that you can cut a model at any angle and position with the cutting tool?" +msgstr "" + +#: resources/data/hints.ini: [hint:Fix Model] +msgid "Fix Model\nDid you know that you can fix a corrupted 3D model to avoid a lot of slicing problems on the Windows system?" +msgstr "" + +#: resources/data/hints.ini: [hint:Timelapse] +msgid "Timelapse\nDid you know that you can generate a timelapse video during each print?" +msgstr "" + +#: resources/data/hints.ini: [hint:Auto-Arrange] +msgid "Auto-Arrange\nDid you know that you can auto-arrange all objects in your project?" +msgstr "" + +#: resources/data/hints.ini: [hint:Auto-Orient] +msgid "Auto-Orient\nDid you know that you can rotate objects to an optimal orientation for printing by a simple click?" +msgstr "" + +#: resources/data/hints.ini: [hint:Lay on Face] +msgid "Lay on Face\nDid you know that you can quickly orient a model so that one of its faces sits on the print bed? Select the \"Place on face\" function or press the F key." +msgstr "" + +#: resources/data/hints.ini: [hint:Object List] +msgid "Object List\nDid you know that you can view all objects/parts in a list and change settings for each object/part?" +msgstr "" + +#: resources/data/hints.ini: [hint:Search Functionality] +msgid "Search Functionality\nDid you know that you use the Search tool to quickly find a specific Orca Slicer setting?" +msgstr "" + +#: resources/data/hints.ini: [hint:Simplify Model] +msgid "Simplify Model\nDid you know that you can reduce the number of triangles in a mesh using the Simplify mesh feature? Right-click the model and select Simplify model." +msgstr "" + +#: resources/data/hints.ini: [hint:Slicing Parameter Table] +msgid "Slicing Parameter Table\nDid you know that you can view all objects/parts on a table and change settings for each object/part?" +msgstr "" + +#: resources/data/hints.ini: [hint:Split to Objects/Parts] +msgid "Split to Objects/Parts\nDid you know that you can split a big object into small ones for easy colorizing or printing?" +msgstr "" + +#: resources/data/hints.ini: [hint:Subtract a Part] +msgid "Subtract a Part\nDid you know that you can subtract one mesh from another using the Negative part modifier? That way you can, for example, create easily resizable holes directly in Orca Slicer." +msgstr "" + +#: resources/data/hints.ini: [hint:STEP] +msgid "STEP\nDid you know that you can improve your print quality by slicing a STEP file instead of an STL?\nOrca Slicer supports slicing STEP files, providing smoother results than a lower resolution STL. Give it a try!" +msgstr "" + +#: resources/data/hints.ini: [hint:Z seam location] +msgid "Z seam location\nDid you know that you can customize the location of the Z seam, and even paint it on your print, to have it in a less visible location? This improves the overall look of your model. Check it out!" +msgstr "" + +#: resources/data/hints.ini: [hint:Fine-tuning for flow rate] +msgid "Fine-tuning for flow rate\nDid you know that flow rate can be fine-tuned for even better-looking prints? Depending on the material, you can improve the overall finish of the printed model by doing some fine-tuning." +msgstr "" + +#: resources/data/hints.ini: [hint:Split your prints into plates] +msgid "Split your prints into plates\nDid you know that you can split a model that has a lot of parts into individual plates ready to print? This will simplify the process of keeping track of all the parts." +msgstr "" + +#: resources/data/hints.ini: [hint:Speed up your print with Adaptive Layer Height] +msgid "Speed up your print with Adaptive Layer Height\nDid you know that you can print a model even faster, by using the Adaptive Layer Height option? Check it out!" +msgstr "" + +#: resources/data/hints.ini: [hint:Support painting] +msgid "Support painting\nDid you know that you can paint the location of your supports? This feature makes it easy to place the support material only on the sections of the model that actually need it." +msgstr "" + +#: resources/data/hints.ini: [hint:Different types of supports] +msgid "Different types of supports\nDid you know that you can choose from multiple types of supports? Tree supports work great for organic models, while saving filament and improving print speed. Check them out!" +msgstr "" + +#: resources/data/hints.ini: [hint:Printing Silk Filament] +msgid "Printing Silk Filament\nDid you know that Silk filament needs special consideration to print it successfully? Higher temperature and lower speed are always recommended for the best results." +msgstr "" + +#: resources/data/hints.ini: [hint:Brim for better adhesion] +msgid "Brim for better adhesion\nDid you know that when printing models have a small contact interface with the printing surface, it's recommended to use a brim?" +msgstr "" + +#: resources/data/hints.ini: [hint:Set parameters for multiple objects] +msgid "Set parameters for multiple objects\nDid you know that you can set slicing parameters for all selected objects at one time?" +msgstr "" + +#: resources/data/hints.ini: [hint:Stack objects] +msgid "Stack objects\nDid you know that you can stack objects as a whole one?" +msgstr "" + +#: resources/data/hints.ini: [hint:Flush into support/objects/infill] +msgid "Flush into support/objects/infill\nDid you know that you can save the wasted filament by flushing them into support/objects/infill during filament change?" +msgstr "" + +#: resources/data/hints.ini: [hint:Improve strength] +msgid "Improve strength\nDid you know that you can use more wall loops and higher sparse infill density to improve the strength of the model?" +msgstr "" + +#: resources/data/hints.ini: [hint:When need to print with the printer door opened] +msgid "When need to print with the printer door opened\nDid you know that opening the printer door can reduce the probability of extruder/hotend clogging when printing lower temperature filament with a higher enclosure temperature. More info about this in the Wiki." +msgstr "" + +#: resources/data/hints.ini: [hint:Avoid warping] +msgid "Avoid warping\nDid you know that when printing materials that are prone to warping such as ABS, appropriately increasing the heatbed temperature can reduce the probability of warping." +msgstr "" diff --git a/localization/i18n/de/OrcaSlicer_de.po b/localization/i18n/de/OrcaSlicer_de.po index 06483be8f7..203a0cbdd2 100644 --- a/localization/i18n/de/OrcaSlicer_de.po +++ b/localization/i18n/de/OrcaSlicer_de.po @@ -2,7 +2,7 @@ msgid "" msgstr "" "Project-Id-Version: Orca Slicer\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-01-13 17:34+0100\n" +"POT-Creation-Date: 2024-01-19 18:27+0100\n" "PO-Revision-Date: \n" "Last-Translator: Heiko Liebscher \n" "Language-Team: \n" @@ -270,16 +270,16 @@ msgid "uniform scale" msgstr "einheitliche Skalierung" msgid "Planar" -msgstr "" +msgstr "Planar" msgid "Dovetail" -msgstr "" +msgstr "Schwalbenschwanz" msgid "Auto" msgstr "Automatisch" msgid "Manual" -msgstr "" +msgstr "Manuell" msgid "Plug" msgstr "Einstecken" @@ -288,10 +288,10 @@ msgid "Dowel" msgstr "Dübel" msgid "Snap" -msgstr "" +msgstr "Einrasten" msgid "Prism" -msgstr "" +msgstr "Prisma" msgid "Frustum" msgstr "Frustum" @@ -303,13 +303,13 @@ msgid "Hexagon" msgstr "Sechseck" msgid "Keep orientation" -msgstr "" +msgstr "Ausrichtung beibehalten" msgid "Place on cut" msgstr "auf den Schnitt legen" msgid "Flip upside down" -msgstr "" +msgstr "Auf den Kopf stellen" msgid "Connectors" msgstr "Verbinder" @@ -327,19 +327,19 @@ msgstr "Form" #. Size in emboss direction #. TRN - Input label. Be short as possible msgid "Depth" -msgstr "" +msgstr "Tiefe" msgid "Groove" -msgstr "" +msgstr "Nut" msgid "Width" msgstr "Breite" msgid "Flap Angle" -msgstr "" +msgstr "Flügelwinkel" msgid "Groove Angle" -msgstr "" +msgstr "Nutwinkel" msgid "Part" msgstr "Teil" @@ -351,21 +351,27 @@ msgid "" "Click to flip the cut plane\n" "Drag to move the cut plane" msgstr "" +"Klicken Sie, um die Schnittebene umzudrehen\n" +"Ziehen Sie, um die Schnittebene zu bewegen" msgid "" "Click to flip the cut plane\n" "Drag to move the cut plane\n" "Right-click a part to assign it to the other side" msgstr "" +"Klicken Sie, um die Schnittebene umzudrehen\n" +"Ziehen Sie, um die Schnittebene zu bewegen\n" +"Klicken Sie mit der rechten Maustaste auf ein Teil, um es der anderen Seite " +"zuzuordnen" msgid "Move cut plane" -msgstr "" +msgstr "Schnittfläche bewegen" msgid "Mode" -msgstr "" +msgstr "Modus" msgid "Change cut mode" -msgstr "" +msgstr "Schnittmodus ändern" msgid "Tolerance" msgstr "Toleranz" @@ -374,7 +380,7 @@ msgid "Drag" msgstr "Ziehen" msgid "Draw cut line" -msgstr "" +msgstr "Schnittlinie zeichnen" msgid "Left click" msgstr "Linksklick" @@ -404,22 +410,22 @@ msgid "Cut" msgstr "Schneiden" msgid "Rotate cut plane" -msgstr "" +msgstr "Schnittfläche drehen" msgid "Remove connectors" msgstr "Verbinder entfernen" msgid "Bulge" -msgstr "" +msgstr "Wölbung" msgid "Bulge proportion related to radius" -msgstr "" +msgstr "Wölbungsverhältnis in Bezug auf den Radius" msgid "Space" msgstr "Platz" msgid "Space proportion related to radius" -msgstr "" +msgstr "Platzverhältnis in Bezug auf den Radius" msgid "Confirm connectors" msgstr "Bestätige Verbinder" @@ -428,26 +434,26 @@ msgid "Cancel" msgstr "Abbrechen" msgid "Build Volume" -msgstr "" +msgstr "Bau Volumen" msgid "Flip cut plane" -msgstr "" +msgstr "Schnittfläche umdrehen" msgid "Groove change" -msgstr "" +msgstr "Nut ändern" msgid "Reset" msgstr "Zurücksetzen" #. TRN: This is an entry in the Undo/Redo stack. The whole line will be 'Edited: (name of whatever was edited)'. msgid "Edited" -msgstr "" +msgstr "Bearbeitet" msgid "Cut position" -msgstr "" +msgstr "Schnittposition" msgid "Reset cutting plane" -msgstr "" +msgstr "Schnittfläche zurücksetzen" msgid "Edit connectors" msgstr "Verbinder ändern" @@ -456,10 +462,10 @@ msgid "Add connectors" msgstr "Verbinder zufügen" msgid "Reset cut" -msgstr "" +msgstr "Schnitt zurücksetzen" msgid "Reset cutting plane and remove connectors" -msgstr "" +msgstr "Schnittfläche zurücksetzen und Verbinder entfernen" msgid "Upper part" msgstr "Oberes Teil" @@ -670,46 +676,46 @@ msgid "Text shape" msgstr "Text zufügen" msgid "Set Mirror" -msgstr "" +msgstr "Spiegel setzen" msgid "Embossed text" -msgstr "" +msgstr "Geprägter Text" msgid "Enter emboss gizmo" -msgstr "" +msgstr "Geprägten Teil eingeben" msgid "Leave emboss gizmo" -msgstr "" +msgstr "Geprägten Teil verlassen" msgid "Embossing actions" -msgstr "" +msgstr "Geprägte Aktionen" msgid "Emboss" -msgstr "" +msgstr "Prägen" msgid "Text-Rotate" -msgstr "" +msgstr "Text-Drehen" msgid "NORMAL" -msgstr "" +msgstr "Normal" msgid "SMALL" -msgstr "" +msgstr "Schmal" msgid "ITALIC" -msgstr "" +msgstr "kursiv" msgid "SWISS" -msgstr "" +msgstr "swiss" msgid "MODERN" -msgstr "" +msgstr "modern" msgid "First font" -msgstr "" +msgstr "erste Schriftart" msgid "Default font" -msgstr "" +msgstr "Standard-Schriftart" msgid "Advanced" msgstr "Erweiterte Einstellungen" @@ -1004,9 +1010,12 @@ msgid "" "Can't load exactly same font(\"%1%\"). Aplication selected a similar " "one(\"%2%\"). You have to specify font for enable edit text." msgstr "" +"Kann genau dieselbe Schriftart (\"%1%\") nicht laden. Die Anwendung hat " +"eine ähnliche (\"%2%\") ausgewählt. Sie müssen eine Schriftart angeben, um " +"die Textbearbeitung zu aktivieren." msgid "No symbol" -msgstr "" +msgstr "Kein Symbol" msgid "Loading" msgstr "Lade" @@ -1079,7 +1088,7 @@ msgid "Leave SVG gizmo" msgstr "SVG-Gizmo verlassen" msgid "SVG actions" -msgstr "" +msgstr "SVG-Aktionen" msgid "SVG" msgstr "SVG" @@ -1254,62 +1263,62 @@ msgstr "Nano SVG-Parser kann nicht aus Datei laden (%1%)." #, boost-format msgid "SVG file does NOT contain a single path to be embossed (%1%)." -msgstr "" +msgstr "SVG-Datei enthält keinen einzigen Pfad zum Prägen (%1%)." msgid "Vertex" -msgstr "" +msgstr "Eckpunkt" msgid "Edge" -msgstr "" +msgstr "Kante" msgid "Plane" -msgstr "" +msgstr "Ebene" msgid "Point on edge" -msgstr "" +msgstr "Punkt auf Kante" msgid "Point on circle" -msgstr "" +msgstr "Punkt auf Kreis" msgid "Point on plane" -msgstr "" +msgstr "Punkt auf Ebene" msgid "Center of edge" -msgstr "" +msgstr "Zentrum der Kante" msgid "Center of circle" -msgstr "" +msgstr "Zentrum des Kreises" msgid "ShiftLeft mouse button" -msgstr "" +msgstr "Umschalttaste + Linksklick" msgid "Select feature" -msgstr "" +msgstr "Feature auswählen" msgid "Select point" -msgstr "" +msgstr "Punkt auswählen" msgid "Delete" msgstr "Löschen" msgid "Restart selection" -msgstr "" +msgstr "Auswahl neu starten" msgid "Esc" msgstr "Esc" msgid "Unselect" -msgstr "" +msgstr "Abwählen" msgid "Measure" -msgstr "" +msgstr "Messen" msgid "Edit to scale" -msgstr "" +msgstr "Bearbeiten auf Skala" msgctxt "Verb" msgid "Scale" -msgstr "" +msgstr "Skalieren" msgid "None" msgstr "Keine" @@ -1321,22 +1330,22 @@ msgid "Length" msgstr "Länge" msgid "Selection" -msgstr "" +msgstr "Auswahl" msgid "Copy to clipboard" msgstr "In Zwischenablage kopieren" msgid "Perpendicular distance" -msgstr "" +msgstr "Senkrechte Entfernung" msgid "Distance" -msgstr "" +msgstr "Entfernung" msgid "Direct distance" -msgstr "" +msgstr "Direkte Entfernung" msgid "Distance XYZ" -msgstr "" +msgstr "Entfernung XYZ" msgid "Ctrl+" msgstr "Strg +" @@ -1697,10 +1706,10 @@ msgid "Cone" msgstr "Kegel" msgid "Disc" -msgstr "" +msgstr "Scheibe" msgid "Torus" -msgstr "" +msgstr "Torus" msgid "Orca Cube" msgstr "Orca Würfel" @@ -1715,7 +1724,7 @@ msgid "Voron Cube" msgstr "Voron Würfel" msgid "Stanford Bunny" -msgstr "" +msgstr "Stanford Hase" msgid "Text" msgstr "T" @@ -1871,7 +1880,7 @@ msgid "Add Primitive" msgstr "Primitiv hinzufügen" msgid "Add Handy models" -msgstr "" +msgstr "Modelle hinzufügen" msgid "Show Labels" msgstr "Bezeichnung anzeigen" @@ -3426,6 +3435,8 @@ msgid "" "Alternate extra wall only works with ensure vertical shell thickness " "disabled. " msgstr "" +"Die alternative zusätzliche Wand funktioniert nur, wenn die vertikale " +"Schalendicke deaktiviert ist." msgid "" "Change these settings automatically? \n" @@ -3433,6 +3444,10 @@ msgid "" "wall\n" "No - Dont use alternate extra wall" msgstr "" +"Diese Einstellungen automatisch ändern? \n" +"Ja - Vertikale Schalendicke deaktivieren und alternative zusätzliche Wand " +"aktivieren\n" +"Nein - Keine alternative zusätzliche Wand verwenden" msgid "" "Prime tower does not work when Adaptive Layer Height or Independent Support " @@ -4062,7 +4077,7 @@ msgstr "Volumen:" msgid "Size:" msgstr "Größe:" -#, c-format, boost-format +#, boost-format msgid "" "Conflicts of gcode paths have been found at layer %d, z = %.2lf mm. Please " "separate the conflicted objects farther (%s <-> %s)." @@ -4143,6 +4158,15 @@ msgstr "Live-Übertragung starten" msgid "Resolution" msgstr "Auflösung" +msgid "Enable" +msgstr "Aktivieren" + +msgid "Hostname or IP" +msgstr "Hostname oder IP" + +msgid "Custom camera source" +msgstr "Benutzerdefinierte Kameraquelle" + msgid "Show \"Live Video\" guide page." msgstr "Anleitungsseite „Live-Video“ anzeigen." @@ -4617,6 +4641,9 @@ msgid "" "Hint: Make sure you have added the corresponding printer before importing " "the configs." msgstr "" +"\n" +"Tipp: Stellen Sie sicher, dass Sie den entsprechenden Drucker hinzugefügt " +"haben, bevor Sie die Konfigurationen importieren." msgid "Import result" msgstr "Ergebnis importieren" @@ -4958,6 +4985,9 @@ msgstr "MicroSD-Karte" msgid "Camera Setting" msgstr "Kameraeinstellung" +msgid "Switch Camera View" +msgstr "Schalte Kameraperspektive" + msgid "Control" msgstr "Steuerung" @@ -6117,7 +6147,7 @@ msgid "Stealth Mode" msgstr "Unsichtbarer Modus" msgid "Check for stable updates only" -msgstr "" +msgstr "Nur nach stabilen Updates suchen" msgid "Metric" msgstr "Metrisch" @@ -7041,6 +7071,8 @@ msgid "" "Layer height is too small.\n" "It will set to min_layer_height\n" msgstr "" +"Die Schichthöhe ist zu klein.\n" +"Sie wird auf min_layer_height gesetzt\n" msgid "" "Layer height exceeds the limit in Printer Settings -> Extruder -> Layer " @@ -7944,13 +7976,13 @@ msgid "Gizmo FDM paint-on seam" msgstr "FDM Naht aufmalen" msgid "Gizmo Text emboss / engrave" -msgstr "" +msgstr "Text prägen / gravieren" msgid "Zoom in" -msgstr "" +msgstr "Vergrößern" msgid "Zoom out" -msgstr "" +msgstr "Verkleinern" msgid "Switch between Prepare/Preview" msgstr "Zwischen Vorbereiten/ Vorschau wechseln" @@ -8122,7 +8154,7 @@ msgid "Idle" msgstr "Inaktiv" msgid "Beta version" -msgstr "" +msgstr "Beta-Version" msgid "Latest version" msgstr "Neueste Version" @@ -8950,6 +8982,39 @@ msgstr "" "bedeutet, dass diese Einstellung deaktiviert ist und die Dicke der unteren " "Schale absolut durch die unteren Schalenschichten bestimmt wird." +msgid "Apply gap fill" +msgstr "Lückenfüllung anwenden" + +msgid "" +"Enables gap fill for the selected surfaces. The minimum gap length that will " +"be filled can be controlled from the filter out tiny gaps option below.\n" +"\n" +"Options:\n" +"1. Everywhere: Applies gap fill to top, bottom and internal solid surfaces\n" +"2. Top and Bottom surfaces: Applies gap fill to top and bottom surfaces " +"only\n" +"3. Nowhere: Disables gap fill\n" +msgstr "" +"Schaltet die Lückenfüllung für die ausgewählten Oberflächen ein. Die " +"minimale Länge der Lücke, die gefüllt wird, kann über die Option \"winzige " +"Lücken herausfiltern\" unten gesteuert werden.\n" +"\n" +"Optionen:\n" +"1. Überall: Füllt Lücken in oberen, unteren und inneren massiven Oberflächen " +"aus\n" +"2. Obere und untere Oberflächen: Füllt Lücken nur in oberen und unteren " +"Oberflächen aus\n" +"3. Nirgendwo: Deaktiviert die Lückenfüllung\n" + +msgid "Everywhere" +msgstr "Überall" + +msgid "Top and bottom surfaces" +msgstr "Obere und untere Oberflächen" + +msgid "Nowhere" +msgstr "Nirgendwo" + msgid "Force cooling for overhang and bridge" msgstr "Zwangskühlung für Überhänge und Brücken" @@ -9420,7 +9485,7 @@ msgstr "" "große Düsen verwenden, sollten Sie diese Funktion deaktivieren." msgid "Don't filter out small internal bridges (experimental)" -msgstr "" +msgstr "Kleine interne Brücken nicht herausfiltern (experimentell)" msgid "" "This option can help reducing pillowing on top surfaces in heavily slanted " @@ -9450,15 +9515,42 @@ msgid "" "overhang. This option is useful for heavily slanted top surface models. " "However, in most cases it creates too many unecessary bridges." msgstr "" +"Diese Option kann dazu beitragen, das Polstern auf Oberflächen mit stark " +"geneigten oder gekrümmten Modellen zu reduzieren.\n" +"\n" +"Standardmäßig werden kleine interne Brücken herausgefiltert und das interne " +"massive Infill wird direkt über dem dünnen Infill gedruckt. Dies funktioniert " +"in den meisten Fällen gut und beschleunigt den Druck ohne zu große " +"Kompromisse bei der Qualität der Oberfläche.\n" +"\n" +"In stark geneigten oder gekrümmten Modellen, insbesondere bei zu geringer " +"Dichte des dünnen Infill, kann dies jedoch zu einer Krümmung des " +"ununterstützten massiven Infill führen, was zu Polstern führt.\n" +"\n" +"Wenn Sie diese Option aktivieren, wird die interne Brückenschicht über dem " +"leicht ununterstützten internen massiven Infill gedruckt. Die folgenden " +"Optionen steuern die Menge der Filterung, d.h. die Menge der erstellten " +"internen Brücken.\n" +"\n" +"Deaktiviert - Deaktiviert diese Option. Dies ist das Standardverhalten und " +"funktioniert in den meisten Fällen gut.\n" +"\n" +"Begrenzte Filterung - Erstellt interne Brücken auf stark geneigten Flächen, " +"vermeidet jedoch die Erstellung von unnötigen internen Brücken. Dies " +"funktioniert gut für die meisten schwierigen Modelle.\n" +"\n" +"Keine Filterung - Erstellt interne Brücken auf jedem potenziellen internen " +"Überhang. Diese Option ist für stark geneigte Oberflächenmodelle nützlich. " +"In den meisten Fällen werden jedoch zu viele unnötige Brücken erstellt." msgid "Disabled" -msgstr "" +msgstr "Deaktiviert" msgid "Limited filtering" -msgstr "" +msgstr "Begrenzte Filterung" msgid "No filtering" -msgstr "" +msgstr "Keine Filterung" msgid "Max bridge length" msgstr "Max Überbrückungslänge" @@ -9501,6 +9593,25 @@ msgstr "" "In der Nähe von schrägen Flächen massive Füllungen hinzufügen, um die " "vertikale Wanddicke zu gewährleisten (obere + untere massive Schichten)." +msgid "Further reduce solid infill on walls (experimental)" +msgstr "Weitere Reduzierung des festen Infill an den Wänden (experimentell)" + +msgid "" +"Further reduces any solid infill applied to walls. As there will be very " +"limited infill supporting solid surfaces, make sure that you are using " +"adequate number of walls to support the part on sloping surfaces.\n" +"\n" +"For heavily sloped surfaces this option is not suitable as it will generate " +"too thin of a top layer and should be disabled." +msgstr "" +"Reduziert das feste Infill an den Wänden weiter. Da nur sehr wenig Infill " +"zur Unterstützung der massiven Oberflächen verwendet wird, stellen Sie " +"sicher, dass Sie eine ausreichende Anzahl von Wänden verwenden, um das Teil " +"auf schrägen Oberflächen zu stützen.\n" +"\n" +"Für stark geneigte Oberflächen ist diese Option nicht geeignet, da sie eine " +"zu dünne obere Schicht erzeugt und deaktiviert werden sollte." + msgid "Top surface pattern" msgstr "Muster der Oberfläche" @@ -10573,10 +10684,10 @@ msgid "Klipper" msgstr "Klipper" msgid "Support multi bed types" -msgstr "" +msgstr "Unterstützung mehrerer Betttypen" msgid "Enable this option if you want to use multiple bed types" -msgstr "" +msgstr "Aktivieren Sie diese Option, wenn Sie mehrere Betttypen verwenden möchten" msgid "Label objects" msgstr "Objekte beschriften" @@ -10755,7 +10866,7 @@ msgstr "" "Beschleunigung zum Drucken verwendet" msgid "Emit limits to G-code" -msgstr "" +msgstr "Werte im G-Code ausgeben" msgid "Machine limits" msgstr "Maschinengrenzen" @@ -10764,6 +10875,10 @@ msgid "" "If enabled, the machine limits will be emitted to G-code file.\n" "This option will be ignored if the g-code flavor is set to Klipper." msgstr "" +"Wenn diese Option aktiviert ist, werden die Maschinengrenzen in die G-Code-" +"Datei ausgegeben.\n" +"Diese Option wird ignoriert, wenn der G-Code-Typ auf Klipper eingestellt " +"ist." msgid "" "This G-code will be used as a code for the pause print. User can insert " @@ -11115,9 +11230,6 @@ msgstr "" "bei komplexeren Modellen verkürzen und Druckzeit sparen, verlangsamt aber " "das Slicen und die G-Code Generierung." -msgid "Enable" -msgstr "Aktivieren" - msgid "Filename format" msgstr "Format des Dateinamens" @@ -11183,7 +11295,7 @@ msgid "Number of walls of every layer" msgstr "Anzahl der Wände jeder Schicht" msgid "Alternate extra wall" -msgstr "" +msgstr "Abwechselnde zusätzliche Wand" msgid "" "This setting adds an extra wall to every other layer. This way the infill " @@ -11195,6 +11307,16 @@ msgid "" "Using lightning infill together with this option is not recommended as there " "is limited infill to anchor the extra perimeters to." msgstr "" +"Diese Einstellung fügt jeder zweiten Schicht eine zusätzliche Wand hinzu. " +"Damit wird die Füllung vertikal zwischen den Wänden eingeklemmt, was zu " +"stärkeren Drucken führt. \n" +"\n" +"Wenn diese Option aktiviert ist, muss die Option zur Sicherstellung der " +"vertikalen Schalendicke deaktiviert werden. \n" +"\n" +"Die Verwendung von Lightning Infill zusammen mit dieser Option wird nicht " +"empfohlen, da die Füllung begrenzt ist, um die zusätzlichen Umfänge zu " +"verankern." msgid "" "If you want to process the output G-code through custom scripts, just list " @@ -11502,7 +11624,7 @@ msgstr "" "innen ausgeführt." msgid "Wipe before external loop" -msgstr "" +msgstr "Wischbewegung vor äußerer Schleife" msgid "" "To minimise visibility of potential overextrusion at the start of an " @@ -11515,6 +11637,15 @@ msgid "" "print order as in these modes it is more likely an external perimeter is " "printed immediately after a deretraction move." msgstr "" +"Um die Sichtbarkeit einer möglichen Überextrusion am Anfang eines äußeren " +"Umfangs zu minimieren, wenn mit der Druckreihenfolge \"Außen/Innen\" oder " +"\"Innen/Außen/Innen\" gedruckt wird, wird der Rückzug etwas nach innen vom " +"Anfang des äußeren Umfangs ausgeführt. Auf diese Weise wird eine mögliche " +"Überextrusion von der Außenfläche verdeckt. \n" +"\n" +"Dies ist nützlich, wenn mit der Druckreihenfolge \"Außen/Innen\" oder " +"\"Innen/Außen/Innen\" gedruckt wird, da in diesen Modi ein äußerer Umfang " +"unmittelbar nach einem Rückzug gedruckt wird." msgid "Wipe speed" msgstr "Wipe Geschwindigkeit" @@ -12498,6 +12629,11 @@ msgid "" "Wipe tower is only compatible with relative mode. It is recommended on most " "printers. Default is checked" msgstr "" +"Relative Extrusion wird empfohlen, wenn die Option \"label_objects\" " +"verwendet wird. Einige Extruder arbeiten besser mit dieser Option " +"deaktiviert (absoluter Extrusionsmodus). Der Reinigungsturm ist nur mit dem " +"relativen Modus kompatibel. Es wird auf den meisten Druckern empfohlen. " +"Standardmäßig ist es aktiviert." msgid "" "Classic wall generator produces walls with constant extrusion width and for " @@ -12591,7 +12727,7 @@ msgstr "" "Bezogen als Prozentsatz auf Düsendurchmesser." msgid "Minimum wall length" -msgstr "" +msgstr "Minimale Wandlänge" msgid "" "Adjust this value to prevent short, unclosed walls from being printed, which " @@ -12603,6 +12739,17 @@ msgid "" "top-surface. 'One wall threshold' is only visibile if this setting is set " "above the default value of 0.5, or if single-wall top surfaces is enabled." msgstr "" +"Passen Sie diesen Wert an, um zu verhindern, dass kurze, offene Wände " +"gedruckt werden, was die Druckzeit erhöhen könnte. Höhere Werte entfernen " +"mehr und längere Wände.\n" +"\n" +"HINWEIS: Die unteren und oberen Oberflächen werden von diesem Wert nicht " +"beeinflusst, um visuelle Lücken an der Außenseite des Modells zu vermeiden. " +"Passen Sie die \"One wall threshold\" in den erweiterten Einstellungen " +"unten an, um die Empfindlichkeit dessen anzupassen, was als obere Oberfläche " +"angesehen wird. \"One wall threshold\" ist nur sichtbar, wenn diese Einstellung " +"über den Standardwert von 0,5 gesetzt ist oder wenn einzelne Wände für die " +"Oberfläche aktiviert sind." msgid "First layer minimum wall width" msgstr "Erste Schicht minimale Wandbreite" @@ -13785,7 +13932,7 @@ msgstr "" "bestehen aus Leerzeichen. Bitte erneut eingeben." msgid "The vendor can not be a number. Please re-enter." -msgstr "" +msgstr "Der Hersteller kann keine Zahl sein. Bitte erneut eingeben." msgid "" "You have not selected a printer or preset yet. Please select at least one." @@ -13808,11 +13955,11 @@ msgstr "" msgid "" "We would rename the presets as \"Vendor Type Serial @printer you " "selected\". \n" -"To add preset for more prinetrs, Please go to printer selection" +"To add preset for more printers, Please go to printer selection" msgstr "" -"Wir würden die Voreinstellungen als \"Hersteller Typ Seriennummer @Drucker " +"Wir würden die Voreinstellungen als \"Hersteller Typ Seriennummer @Drucker, " "den Sie ausgewählt haben\" umbenennen. \n" -"Um Voreinstellungen für mehr Drucker hinzuzufügen, gehen Sie bitte zur " +"Um Voreinstellungen für weitere Drucker hinzuzufügen, gehen Sie bitte zur " "Druckerauswahl" msgid "Create Printer/Nozzle" @@ -14406,6 +14553,409 @@ msgstr "" "Nachrichtentext: \"%1%\"\n" "Fehler: \"%2%\"" +#: resources/data/hints.ini: [hint:Precise wall] +msgid "" +"Precise wall\n" +"Did you know that turning on precise wall can improve precision and layer " +"consistency?" +msgstr "" +"Präzise Wand\n" +"Wussten Sie, dass Sie durch das Einschalten der präzisen Wand die Präzision " +"und die Schichtkonsistenz verbessern können?" + +#: resources/data/hints.ini: [hint:Sandwich mode] +msgid "" +"Sandwich mode\n" +"Did you know that you can use sandwich mode (inner-outer-inner) to improve " +"precision and layer consistency if your model doesn't have very steep " +"overhangs?" +msgstr "" +"Sandwich-Modus\n" +"Wussten Sie, dass Sie den Sandwich-Modus (innen-außen-innen) verwenden " +"können, um die Präzision und die Schichtkonsistenz zu verbessern, wenn Ihr " +"Modell keine sehr steilen Überhänge hat?" + +#: resources/data/hints.ini: [hint:Chamber temperature] +msgid "" +"Chamber temperature\n" +"Did you know that OrcaSlicer supports chamber temperature?" +msgstr "" +"Kammertemperatur\n" +"Wussten Sie, dass OrcaSlicer die Kammertemperatur unterstützt?" + +#: resources/data/hints.ini: [hint:Calibration] +msgid "" +"Calibration\n" +"Did you know that calibrating your printer can do wonders? Check out our " +"beloved calibration solution in OrcaSlicer." +msgstr "" +"Kalibrierung\n" +"Wussten Sie, dass die Kalibrierung Ihres Druckers Wunder bewirken kann? " +"Schauen Sie sich unsere beliebte Kalibrierungslösung in OrcaSlicer an." + +#: resources/data/hints.ini: [hint:Auxiliary fan] +msgid "" +"Auxiliary fan\n" +"Did you know that OrcaSlicer supports Auxiliary part cooling fan?" +msgstr "" +"Hilfsventilator\n" +"Wussten Sie, dass OrcaSlicer einen Hilfskühlventilator unterstützt?" + +#: resources/data/hints.ini: [hint:Air filtration] +msgid "" +"Air filtration/Exhuast Fan\n" +"Did you know that OrcaSlicer can support Air filtration/Exhuast Fan?" +msgstr "" +"Luftfiltration/Abluftventilator\n" +"Wussten Sie, dass OrcaSlicer eine Luftfiltration/Abluftventilator " +"unterstützen kann?" + +#: resources/data/hints.ini: [hint:G-code window] +msgid "" +"G-code window\n" +"You can turn on/off the G-code window by pressing the C key." +msgstr "" +"G-Code-Fenster\n" +"Sie können das G-Code-Fenster ein- und ausschalten, indem Sie die Taste " +"C drücken." + +#: resources/data/hints.ini: [hint:Switch workspaces] +msgid "" +"Switch workspaces\n" +"You can switch between Prepare and Preview workspaces by " +"pressing the Tab key." +msgstr "" +"Arbeitsbereiche wechseln\n" +"Sie können zwischen den Arbeitsbereichen Vorbereiten und Preview wechseln, indem Sie die Taste Tab drücken." + +#: resources/data/hints.ini: [hint:How to use keyboard shortcuts] +msgid "" +"How to use keyboard shortcuts\n" +"Did you know that Orca Slicer offers a wide range of keyboard shortcuts and " +"3D scene operations." +msgstr "" +"Tastenkombinationen verwenden\n" +"Wussten Sie, dass Orca Slicer eine Vielzahl von Tastenkombinationen und 3D-" +"Szenenoperationen bietet." + +#: resources/data/hints.ini: [hint:Reverse on odd] +msgid "" +"Reverse on odd\n" +"Did you know that Reverse on odd feature can significantly improve " +"the surface quality of your overhangs?" +msgstr "" +"Umkehrung bei ungeraden\n" +"Wussten Sie, dass die Funktion Umkehrung bei ungeraden die " +"Oberflächenqualität Ihrer Überhänge erheblich verbessern kann?" + +#: resources/data/hints.ini: [hint:Cut Tool] +msgid "" +"Cut Tool\n" +"Did you know that you can cut a model at any angle and position with the " +"cutting tool?" +msgstr "" +"Schneidwerkzeug\n" +"Wussten Sie, dass Sie ein Modell mit dem Schneidwerkzeug in jedem Winkel und " +"an jeder Position schneiden können?" + +#: resources/data/hints.ini: [hint:Fix Model] +msgid "" +"Fix Model\n" +"Did you know that you can fix a corrupted 3D model to avoid a lot of slicing " +"problems on the Windows system?" +msgstr "" +"Modell reparieren\n" +"Wussten Sie, dass Sie ein beschädigtes 3D-Modell reparieren können, um eine " +"Vielzahl von Slicing-Problemen auf dem Windows-System zu vermeiden?" + +#: resources/data/hints.ini: [hint:Timelapse] +msgid "" +"Timelapse\n" +"Did you know that you can generate a timelapse video during each print?" +msgstr "" +"Zeitraffer\n" +"Wussten Sie, dass Sie während jedes Drucks ein Zeitraffervideo erstellen " +"können?" + +#: resources/data/hints.ini: [hint:Auto-Arrange] +msgid "" +"Auto-Arrange\n" +"Did you know that you can auto-arrange all objects in your project?" +msgstr "" +"Automatisch anordnen\n" +"Wussten Sie, dass Sie alle Objekte in Ihrem Projekt automatisch anordnen " +"können?" + +#: resources/data/hints.ini: [hint:Auto-Orient] +msgid "" +"Auto-Orient\n" +"Did you know that you can rotate objects to an optimal orientation for " +"printing by a simple click?" +msgstr "" +"Automatisch ausrichten\n" +"Wussten Sie, dass Sie Objekte durch einen einfachen Klick in eine optimale " +"Druckausrichtung drehen können?" + +#: resources/data/hints.ini: [hint:Lay on Face] +msgid "" +"Lay on Face\n" +"Did you know that you can quickly orient a model so that one of its faces " +"sits on the print bed? Select the \"Place on face\" function or press the " +"F key." +msgstr "" +"Auf Fläche legen\n" +"Wussten Sie, dass Sie ein Modell schnell so ausrichten können, dass eine " +"seiner Flächen auf dem Druckbett liegt? Wählen Sie die Funktion \"Auf Fläche " +"legen\" oder drücken Sie die Taste F." + +#: resources/data/hints.ini: [hint:Object List] +msgid "" +"Object List\n" +"Did you know that you can view all objects/parts in a list and change " +"settings for each object/part?" +msgstr "" +"Objekt-Liste\n" +"Wussten Sie, dass Sie alle Objekte/Teile in einer Liste anzeigen und die " +"Einstellungen für jedes Objekt/Teil ändern können?" + +#: resources/data/hints.ini: [hint:Search Functionality] +msgid "" +"Search Functionality\n" +"Did you know that you use the Search tool to quickly find a specific Orca " +"Slicer setting?" +msgstr "" +"Suchfunktion\n" +"Wussten Sie, dass Sie das Suchwerkzeug verwenden können, um schnell eine " +"bestimmte Orca Slicer-Einstellung zu finden?" + +#: resources/data/hints.ini: [hint:Simplify Model] +msgid "" +"Simplify Model\n" +"Did you know that you can reduce the number of triangles in a mesh using the " +"Simplify mesh feature? Right-click the model and select Simplify model." +msgstr "" +"Modell vereinfachen\n" +"Wussten Sie, dass Sie die Anzahl der Dreiecke in einem Netz mithilfe der " +"Funktion \"Netz vereinfachen\" reduzieren können? Klicken Sie mit der " +"rechten Maustaste auf das Modell und wählen Sie \"Modell vereinfachen\"." + +#: resources/data/hints.ini: [hint:Slicing Parameter Table] +msgid "" +"Slicing Parameter Table\n" +"Did you know that you can view all objects/parts on a table and change " +"settings for each object/part?" +msgstr "" +"Parametertabelle für das Slicen\n" +"Wussten Sie, dass Sie alle Objekte/Teile in einer Tabelle anzeigen und die " +"Einstellungen für jedes Objekt/Teil ändern können?" + +#: resources/data/hints.ini: [hint:Split to Objects/Parts] +msgid "" +"Split to Objects/Parts\n" +"Did you know that you can split a big object into small ones for easy " +"colorizing or printing?" +msgstr "" +"In Objekte/Teile aufteilen\n" +"Wussten Sie, dass Sie ein großes Objekt in kleine Teile aufteilen können, um " +"es leichter einzufärben oder drucken zu können?" + +#: resources/data/hints.ini: [hint:Subtract a Part] +msgid "" +"Subtract a Part\n" +"Did you know that you can subtract one mesh from another using the Negative " +"part modifier? That way you can, for example, create easily resizable holes " +"directly in Orca Slicer." +msgstr "" +"Teile entfernen\n" +"Wussten Sie, dass Sie ein Netz von einem anderen abziehen können, indem Sie " +"den negativen Teilmodifikator verwenden? Auf diese Weise können Sie " +"beispielsweise direkt in Orca Slicer leicht skalierbare Löcher erstellen." + +#: resources/data/hints.ini: [hint:STEP] +msgid "" +"STEP\n" +"Did you know that you can improve your print quality by slicing a STEP file " +"instead of an STL?\n" +"Orca Slicer supports slicing STEP files, providing smoother results than a " +"lower resolution STL. Give it a try!" +msgstr "" +"STEP\n" +"Wussten Sie, dass Sie Ihre Druckqualität verbessern können, indem Sie eine " +"STEP-Datei anstelle einer STL-Datei slicen?\n" +"Orca Slicer unterstützt das Slicen von STEP-Dateien und liefert glattere " +"Ergebnisse als eine STL mit geringerer Auflösung. Probiere es aus!" + +#: resources/data/hints.ini: [hint:Z seam location] +msgid "" +"Z seam location\n" +"Did you know that you can customize the location of the Z seam, and even " +"paint it on your print, to have it in a less visible location? This improves " +"the overall look of your model. Check it out!" +msgstr "" +"Position der Z-Naht\n" +"Wussten Sie, dass Sie die Position der Z-Naht anpassen und sie sogar auf " +"Ihren Druck malen können, um sie an einer weniger sichtbaren Stelle " +"anzubringen? Dadurch wird das Gesamtbild Ihres Modells verbessert. Probiere " +"es aus!" + +#: resources/data/hints.ini: [hint:Fine-tuning for flow rate] +msgid "" +"Fine-tuning for flow rate\n" +"Did you know that flow rate can be fine-tuned for even better-looking " +"prints? Depending on the material, you can improve the overall finish of the " +"printed model by doing some fine-tuning." +msgstr "" +"Feineinstellung der Flussrate\n" +"Wussten Sie, dass die Flussgeschwindigkeit des Filament fein eingestellt " +"werden kann, um noch besser aussehende Drucke zu erhalten? Je nach Material " +"können Sie das Gesamtergebnis des gedruckten Modells verbessern, indem Sie " +"eine Feineinstellung vornehmen." + +#: resources/data/hints.ini: [hint:Split your prints into plates] +msgid "" +"Split your prints into plates\n" +"Did you know that you can split a model that has a lot of parts into " +"individual plates ready to print? This will simplify the process of keeping " +"track of all the parts." +msgstr "" +"Drucke in mehrere Druckplatten aufteilen\n" +"Wussten Sie, dass Sie ein Modell, das aus vielen Teilen besteht, in einzelne " +"Druckplatten aufteilen können? Dadurch wird es einfacher, den Überblick über " +"alle Teile zu behalten." + +#: resources/data/hints.ini: [hint:Speed up your print with Adaptive Layer +#: Height] +msgid "" +"Speed up your print with Adaptive Layer Height\n" +"Did you know that you can print a model even faster, by using the Adaptive " +"Layer Height option? Check it out!" +msgstr "" +"Beschleunigen Sie Ihren Druck mit adaptiver Schichthöhe\n" +"Wussten Sie, dass Sie ein Modell noch schneller drucken können, indem Sie " +"die Option Adaptive Schichthöhe verwenden? Probiere es aus!" + +#: resources/data/hints.ini: [hint:Support painting] +msgid "" +"Support painting\n" +"Did you know that you can paint the location of your supports? This feature " +"makes it easy to place the support material only on the sections of the " +"model that actually need it." +msgstr "" +"Stützen malen\n" +"Wussten Sie, dass Sie die Position der Stützen aufmalen können? Diese " +"Funktion macht es möglich, das Stützmaterial nur auf die Bereiche des " +"Modells zu platzieren, die es tatsächlich benötigen." + +#: resources/data/hints.ini: [hint:Different types of supports] +msgid "" +"Different types of supports\n" +"Did you know that you can choose from multiple types of supports? Tree " +"supports work great for organic models, while saving filament and improving " +"print speed. Check them out!" +msgstr "" +"Verschiedene Arten von Stützstrukturen\n" +"Wussten Sie, dass Sie zwischen verschiedenen Arten von Stützen wählen " +"können? Baumstützen eignet sich hervorragend für organische Modelle, sparen " +"Filament und erhöhen die Druckgeschwindigkeit. Probiere sie aus!" + +#: resources/data/hints.ini: [hint:Printing Silk Filament] +msgid "" +"Printing Silk Filament\n" +"Did you know that Silk filament needs special consideration to print it " +"successfully? Higher temperature and lower speed are always recommended for " +"the best results." +msgstr "" +"Drucken von Seidenfilament\n" +"Wussten Sie, dass Seidenfilament besondere Überlegungen erfordert, um es " +"erfolgreich zu drucken? Höhere Temperaturen und niedrigere Geschwindigkeiten " +"werden immer für die besten Ergebnisse empfohlen." + +#: resources/data/hints.ini: [hint:Brim for better adhesion] +msgid "" +"Brim for better adhesion\n" +"Did you know that when printing models have a small contact interface with " +"the printing surface, it's recommended to use a brim?" +msgstr "" +"Rand für bessere Haftung\n" +"Wussten Sie, dass bei gedruckten Modellen, die eine kleine Kontaktfläche mit " +"der Druckoberfläche haben, die Verwendung eines Randes empfohlen wird?" + +#: resources/data/hints.ini: [hint:Set parameters for multiple objects] +msgid "" +"Set parameters for multiple objects\n" +"Did you know that you can set slicing parameters for all selected objects at " +"one time?" +msgstr "" +"Parameter für mehrere Objekte festlegen\n" +"Wussten Sie schon, dass Sie die Slicingparameter für alle ausgewählten " +"Objekte gleichzeitig festlegen können?" + +#: resources/data/hints.ini: [hint:Stack objects] +msgid "" +"Stack objects\n" +"Did you know that you can stack objects as a whole one?" +msgstr "" +"Objekte stapeln\n" +"Wussten Sie, dass Sie Objekte als Ganzes stapeln können?" + +#: resources/data/hints.ini: [hint:Flush into support/objects/infill] +msgid "" +"Flush into support/objects/infill\n" +"Did you know that you can save the wasted filament by flushing them into " +"support/objects/infill during filament change?" +msgstr "" +"Reinigen in Stützstrukturen/Objekten/Füllungen\n" +"Wussten Sie schon, dass Sie die Menge an verschwendetem Filament reduzieren " +"können, indem Sie es während des Filamentwechsels in Stützstrukturen/" +"Objekten/Füllungen reinigen?" + +#: resources/data/hints.ini: [hint:Improve strength] +msgid "" +"Improve strength\n" +"Did you know that you can use more wall loops and higher sparse infill " +"density to improve the strength of the model?" +msgstr "" +"Festigkeit verbessern\n" +"Wussten Sie, dass Sie die Festigkeit des Modells durch mehr Wandschleifen " +"und eine höhere Dichte der Füllung verbessern können?" + +#: resources/data/hints.ini: [hint:When need to print with the printer door +#: opened] +msgid "" +"When need to print with the printer door opened\n" +"Did you know that opening the printer door can reduce the probability of " +"extruder/hotend clogging when printing lower temperature filament with a " +"higher enclosure temperature. More info about this in the Wiki." +msgstr "" +"Wenn mit geöffneter Druckertür gedruckt werden muss\n" +"Wussten Sie, dass das Öffnen der Druckertür die Wahrscheinlichkeit eines " +"Verstopfens des Extruders/Hotends beim Drucken von Filamenten mit niedriger " +"Temperatur und höherer Gehäusetemperatur verringern kann. Weitere " +"Informationen dazu finden Sie im Wiki." + +#: resources/data/hints.ini: [hint:Avoid warping] +msgid "" +"Avoid warping\n" +"Did you know that when printing materials that are prone to warping such as " +"ABS, appropriately increasing the heatbed temperature can reduce the " +"probability of warping." +msgstr "" +"Verwerfungen vermeiden\n" +"Wussten Sie, dass beim Drucken von Materialien, die zu Verwerfungen neigen, " +"wie z.B. ABS, durch eine entsprechende Erhöhung der Heizbetttemperatur die " +"Wahrscheinlichkeit von Verwerfungen verringert werden kann." + +#~ msgid "" +#~ "We would rename the presets as \"Vendor Type Serial @printer you " +#~ "selected\". \n" +#~ "To add preset for more prinetrs, Please go to printer selection" +#~ msgstr "" +#~ "Wir würden die Voreinstellungen als \"Hersteller Typ Seriennummer " +#~ "@Drucker den Sie ausgewählt haben\" umbenennen. \n" +#~ "Um Voreinstellungen für mehr Drucker hinzuzufügen, gehen Sie bitte zur " +#~ "Druckerauswahl" + #~ msgid "The Config can not be loaded." #~ msgstr "Die Konfiguration kann nicht geladen werden." @@ -14414,362 +14964,6 @@ msgstr "" #~ "Die 3mf wurde mit einer alten Version von OrcaSlicer generiert, lade nur " #~ "die Geometriedaten." -#~ msgid "" -#~ "Precise wall\n" -#~ "Did you know that turning on precise wall can improve precision and layer " -#~ "consistency?" -#~ msgstr "" -#~ "Präzise Wand\n" -#~ "Wussten Sie, dass Sie durch das Einschalten der präzisen Wand die " -#~ "Präzision und die Schichtkonsistenz verbessern können?" - -#~ msgid "" -#~ "Sandwich mode\n" -#~ "Did you know that you can use sandwich mode (inner-outer-inner) to " -#~ "improve precision and layer consistency if your model doesn't have very " -#~ "steep overhangs?" -#~ msgstr "" -#~ "Sandwich-Modus\n" -#~ "Wussten Sie, dass Sie den Sandwich-Modus (innen-außen-innen) verwenden " -#~ "können, um die Präzision und die Schichtkonsistenz zu verbessern, wenn " -#~ "Ihr Modell keine sehr steilen Überhänge hat?" - -#~ msgid "" -#~ "Chamber temperature\n" -#~ "Did you know that OrcaSlicer supports chamber temperature?" -#~ msgstr "" -#~ "Kammertemperatur\n" -#~ "Wussten Sie, dass OrcaSlicer die Kammertemperatur unterstützt?" - -#~ msgid "" -#~ "Calibration\n" -#~ "Did you know that calibrating your printer can do wonders? Check out our " -#~ "beloved calibration solution in OrcaSlicer." -#~ msgstr "" -#~ "Kalibrierung\n" -#~ "Wussten Sie, dass die Kalibrierung Ihres Druckers Wunder bewirken kann? " -#~ "Schauen Sie sich unsere beliebte Kalibrierungslösung in OrcaSlicer an." - -#~ msgid "" -#~ "Auxiliary fan\n" -#~ "Did you know that OrcaSlicer supports Auxiliary part cooling fan?" -#~ msgstr "" -#~ "Hilfsventilator\n" -#~ "Wussten Sie, dass OrcaSlicer einen Hilfskühlventilator unterstützt?" - -#~ msgid "" -#~ "Air filtration/Exhuast Fan\n" -#~ "Did you know that OrcaSlicer can support Air filtration/Exhuast Fan?" -#~ msgstr "" -#~ "Luftfiltration/Abluftventilator\n" -#~ "Wussten Sie, dass OrcaSlicer eine Luftfiltration/Abluftventilator " -#~ "unterstützen kann?" - -#~ msgid "" -#~ "G-code window\n" -#~ "You can turn on/off the G-code window by pressing the C key." -#~ msgstr "" -#~ "G-Code-Fenster\n" -#~ "Sie können das G-Code-Fenster ein- und ausschalten, indem Sie die Taste " -#~ "C drücken." - -#~ msgid "" -#~ "Switch workspaces\n" -#~ "You can switch between Prepare and Preview workspaces by " -#~ "pressing the Tab key." -#~ msgstr "" -#~ "Arbeitsbereiche wechseln\n" -#~ "Sie können zwischen den Arbeitsbereichen Vorbereiten und " -#~ "Preview wechseln, indem Sie die Taste Tab drücken." - -#~ msgid "" -#~ "How to use keyboard shortcuts\n" -#~ "Did you know that Orca Slicer offers a wide range of keyboard shortcuts " -#~ "and 3D scene operations." -#~ msgstr "" -#~ "Tastenkombinationen verwenden\n" -#~ "Wussten Sie, dass Orca Slicer eine Vielzahl von Tastenkombinationen und " -#~ "3D-Szenenoperationen bietet." - -#~ msgid "" -#~ "Reverse on odd\n" -#~ "Did you know that Reverse on odd feature can significantly improve " -#~ "the surface quality of your overhangs?" -#~ msgstr "" -#~ "Umkehrung bei ungeraden\n" -#~ "Wussten Sie, dass die Funktion Umkehrung bei ungeraden die " -#~ "Oberflächenqualität Ihrer Überhänge erheblich verbessern kann?" - -#~ msgid "" -#~ "Cut Tool\n" -#~ "Did you know that you can cut a model at any angle and position with the " -#~ "cutting tool?" -#~ msgstr "" -#~ "Schneidwerkzeug\n" -#~ "Wussten Sie, dass Sie ein Modell mit dem Schneidwerkzeug in jedem Winkel " -#~ "und an jeder Position schneiden können?" - -#~ msgid "" -#~ "Fix Model\n" -#~ "Did you know that you can fix a corrupted 3D model to avoid a lot of " -#~ "slicing problems on the Windows system?" -#~ msgstr "" -#~ "Modell reparieren\n" -#~ "Wussten Sie, dass Sie ein beschädigtes 3D-Modell reparieren können, um " -#~ "eine Vielzahl von Slicing-Problemen auf dem Windows-System zu vermeiden?" - -#~ msgid "" -#~ "Timelapse\n" -#~ "Did you know that you can generate a timelapse video during each print?" -#~ msgstr "" -#~ "Zeitraffer\n" -#~ "Wussten Sie, dass Sie während jedes Drucks ein Zeitraffervideo erstellen " -#~ "können?" - -#~ msgid "" -#~ "Auto-Arrange\n" -#~ "Did you know that you can auto-arrange all objects in your project?" -#~ msgstr "" -#~ "Automatisch anordnen\n" -#~ "Wussten Sie, dass Sie alle Objekte in Ihrem Projekt automatisch anordnen " -#~ "können?" - -#~ msgid "" -#~ "Auto-Orient\n" -#~ "Did you know that you can rotate objects to an optimal orientation for " -#~ "printing by a simple click?" -#~ msgstr "" -#~ "Automatisch ausrichten\n" -#~ "Wussten Sie, dass Sie Objekte durch einen einfachen Klick in eine " -#~ "optimale Druckausrichtung drehen können?" - -#~ msgid "" -#~ "Lay on Face\n" -#~ "Did you know that you can quickly orient a model so that one of its faces " -#~ "sits on the print bed? Select the \"Place on face\" function or press the " -#~ "F key." -#~ msgstr "" -#~ "Auf Fläche legen\n" -#~ "Wussten Sie, dass Sie ein Modell schnell so ausrichten können, dass eine " -#~ "seiner Flächen auf dem Druckbett liegt? Wählen Sie die Funktion \"Auf " -#~ "Fläche legen\" oder drücken Sie die Taste F." - -#~ msgid "" -#~ "Object List\n" -#~ "Did you know that you can view all objects/parts in a list and change " -#~ "settings for each object/part?" -#~ msgstr "" -#~ "Objekt-Liste\n" -#~ "Wussten Sie, dass Sie alle Objekte/Teile in einer Liste anzeigen und die " -#~ "Einstellungen für jedes Objekt/Teil ändern können?" - -#~ msgid "" -#~ "Search Functionality\n" -#~ "Did you know that you use the Search tool to quickly find a specific Orca " -#~ "Slicer setting?" -#~ msgstr "" -#~ "Suchfunktion\n" -#~ "Wussten Sie, dass Sie das Suchwerkzeug verwenden können, um schnell eine " -#~ "bestimmte Orca Slicer-Einstellung zu finden?" - -#~ msgid "" -#~ "Simplify Model\n" -#~ "Did you know that you can reduce the number of triangles in a mesh using " -#~ "the Simplify mesh feature? Right-click the model and select Simplify " -#~ "model." -#~ msgstr "" -#~ "Modell vereinfachen\n" -#~ "Wussten Sie, dass Sie die Anzahl der Dreiecke in einem Netz mithilfe der " -#~ "Funktion \"Netz vereinfachen\" reduzieren können? Klicken Sie mit der " -#~ "rechten Maustaste auf das Modell und wählen Sie \"Modell vereinfachen\"." - -#~ msgid "" -#~ "Slicing Parameter Table\n" -#~ "Did you know that you can view all objects/parts on a table and change " -#~ "settings for each object/part?" -#~ msgstr "" -#~ "Parametertabelle für das Slicen\n" -#~ "Wussten Sie, dass Sie alle Objekte/Teile in einer Tabelle anzeigen und " -#~ "die Einstellungen für jedes Objekt/Teil ändern können?" - -#~ msgid "" -#~ "Split to Objects/Parts\n" -#~ "Did you know that you can split a big object into small ones for easy " -#~ "colorizing or printing?" -#~ msgstr "" -#~ "In Objekte/Teile aufteilen\n" -#~ "Wussten Sie, dass Sie ein großes Objekt in kleine Teile aufteilen können, " -#~ "um es leichter einzufärben oder drucken zu können?" - -#~ msgid "" -#~ "Subtract a Part\n" -#~ "Did you know that you can subtract one mesh from another using the " -#~ "Negative part modifier? That way you can, for example, create easily " -#~ "resizable holes directly in Orca Slicer." -#~ msgstr "" -#~ "Teile entfernen\n" -#~ "Wussten Sie, dass Sie ein Netz von einem anderen abziehen können, indem " -#~ "Sie den negativen Teilmodifikator verwenden? Auf diese Weise können Sie " -#~ "beispielsweise direkt in Orca Slicer leicht skalierbare Löcher erstellen." - -#~ msgid "" -#~ "STEP\n" -#~ "Did you know that you can improve your print quality by slicing a STEP " -#~ "file instead of an STL?\n" -#~ "Orca Slicer supports slicing STEP files, providing smoother results than " -#~ "a lower resolution STL. Give it a try!" -#~ msgstr "" -#~ "STEP\n" -#~ "Wussten Sie, dass Sie Ihre Druckqualität verbessern können, indem Sie " -#~ "eine STEP-Datei anstelle einer STL-Datei slicen?\n" -#~ "Orca Slicer unterstützt das Slicen von STEP-Dateien und liefert glattere " -#~ "Ergebnisse als eine STL mit geringerer Auflösung. Probiere es aus!" - -#~ msgid "" -#~ "Z seam location\n" -#~ "Did you know that you can customize the location of the Z seam, and even " -#~ "paint it on your print, to have it in a less visible location? This " -#~ "improves the overall look of your model. Check it out!" -#~ msgstr "" -#~ "Position der Z-Naht\n" -#~ "Wussten Sie, dass Sie die Position der Z-Naht anpassen und sie sogar auf " -#~ "Ihren Druck malen können, um sie an einer weniger sichtbaren Stelle " -#~ "anzubringen? Dadurch wird das Gesamtbild Ihres Modells verbessert. " -#~ "Probiere es aus!" - -#~ msgid "" -#~ "Fine-tuning for flow rate\n" -#~ "Did you know that flow rate can be fine-tuned for even better-looking " -#~ "prints? Depending on the material, you can improve the overall finish of " -#~ "the printed model by doing some fine-tuning." -#~ msgstr "" -#~ "Feineinstellung der Flussrate\n" -#~ "Wussten Sie, dass die Flussgeschwindigkeit des Filament fein eingestellt " -#~ "werden kann, um noch besser aussehende Drucke zu erhalten? Je nach " -#~ "Material können Sie das Gesamtergebnis des gedruckten Modells verbessern, " -#~ "indem Sie eine Feineinstellung vornehmen." - -#~ msgid "" -#~ "Split your prints into plates\n" -#~ "Did you know that you can split a model that has a lot of parts into " -#~ "individual plates ready to print? This will simplify the process of " -#~ "keeping track of all the parts." -#~ msgstr "" -#~ "Drucke in mehrere Druckplatten aufteilen\n" -#~ "Wussten Sie, dass Sie ein Modell, das aus vielen Teilen besteht, in " -#~ "einzelne Druckplatten aufteilen können? Dadurch wird es einfacher, den " -#~ "Überblick über alle Teile zu behalten." - -#~ msgid "" -#~ "Speed up your print with Adaptive Layer Height\n" -#~ "Did you know that you can print a model even faster, by using the " -#~ "Adaptive Layer Height option? Check it out!" -#~ msgstr "" -#~ "Beschleunigen Sie Ihren Druck mit adaptiver Schichthöhe\n" -#~ "Wussten Sie, dass Sie ein Modell noch schneller drucken können, indem Sie " -#~ "die Option Adaptive Schichthöhe verwenden? Probiere es aus!" - -#~ msgid "" -#~ "Support painting\n" -#~ "Did you know that you can paint the location of your supports? This " -#~ "feature makes it easy to place the support material only on the sections " -#~ "of the model that actually need it." -#~ msgstr "" -#~ "Stützen malen\n" -#~ "Wussten Sie, dass Sie die Position der Stützen aufmalen können? Diese " -#~ "Funktion macht es möglich, das Stützmaterial nur auf die Bereiche des " -#~ "Modells zu platzieren, die es tatsächlich benötigen." - -#~ msgid "" -#~ "Different types of supports\n" -#~ "Did you know that you can choose from multiple types of supports? Tree " -#~ "supports work great for organic models, while saving filament and " -#~ "improving print speed. Check them out!" -#~ msgstr "" -#~ "Verschiedene Arten von Stützstrukturen\n" -#~ "Wussten Sie, dass Sie zwischen verschiedenen Arten von Stützen wählen " -#~ "können? Baumstützen eignet sich hervorragend für organische Modelle, " -#~ "sparen Filament und erhöhen die Druckgeschwindigkeit. Probiere sie aus!" - -#~ msgid "" -#~ "Printing Silk Filament\n" -#~ "Did you know that Silk filament needs special consideration to print it " -#~ "successfully? Higher temperature and lower speed are always recommended " -#~ "for the best results." -#~ msgstr "" -#~ "Drucken von Seidenfilament\n" -#~ "Wussten Sie, dass Seidenfilament besondere Überlegungen erfordert, um es " -#~ "erfolgreich zu drucken? Höhere Temperaturen und niedrigere " -#~ "Geschwindigkeiten werden immer für die besten Ergebnisse empfohlen." - -#~ msgid "" -#~ "Brim for better adhesion\n" -#~ "Did you know that when printing models have a small contact interface " -#~ "with the printing surface, it's recommended to use a brim?" -#~ msgstr "" -#~ "Rand für bessere Haftung\n" -#~ "Wussten Sie, dass bei gedruckten Modellen, die eine kleine Kontaktfläche " -#~ "mit der Druckoberfläche haben, die Verwendung eines Randes empfohlen wird?" - -#~ msgid "" -#~ "Set parameters for multiple objects\n" -#~ "Did you know that you can set slicing parameters for all selected objects " -#~ "at one time?" -#~ msgstr "" -#~ "Parameter für mehrere Objekte festlegen\n" -#~ "Wussten Sie schon, dass Sie die Slicingparameter für alle ausgewählten " -#~ "Objekte gleichzeitig festlegen können?" - -#~ msgid "" -#~ "Stack objects\n" -#~ "Did you know that you can stack objects as a whole one?" -#~ msgstr "" -#~ "Objekte stapeln\n" -#~ "Wussten Sie, dass Sie Objekte als Ganzes stapeln können?" - -#~ msgid "" -#~ "Flush into support/objects/infill\n" -#~ "Did you know that you can save the wasted filament by flushing them into " -#~ "support/objects/infill during filament change?" -#~ msgstr "" -#~ "Reinigen in Stützstrukturen/Objekten/Füllungen\n" -#~ "Wussten Sie schon, dass Sie die Menge an verschwendetem Filament " -#~ "reduzieren können, indem Sie es während des Filamentwechsels in " -#~ "Stützstrukturen/Objekten/Füllungen reinigen?" - -#~ msgid "" -#~ "Improve strength\n" -#~ "Did you know that you can use more wall loops and higher sparse infill " -#~ "density to improve the strength of the model?" -#~ msgstr "" -#~ "Festigkeit verbessern\n" -#~ "Wussten Sie, dass Sie die Festigkeit des Modells durch mehr Wandschleifen " -#~ "und eine höhere Dichte der Füllung verbessern können?" - -#~ msgid "" -#~ "When need to print with the printer door opened\n" -#~ "Did you know that opening the printer door can reduce the probability of " -#~ "extruder/hotend clogging when printing lower temperature filament with a " -#~ "higher enclosure temperature. More info about this in the Wiki." -#~ msgstr "" -#~ "Wenn mit geöffneter Druckertür gedruckt werden muss\n" -#~ "Wussten Sie, dass das Öffnen der Druckertür die Wahrscheinlichkeit eines " -#~ "Verstopfens des Extruders/Hotends beim Drucken von Filamenten mit " -#~ "niedriger Temperatur und höherer Gehäusetemperatur verringern kann. " -#~ "Weitere Informationen dazu finden Sie im Wiki." - -#~ msgid "" -#~ "Avoid warping\n" -#~ "Did you know that when printing materials that are prone to warping such " -#~ "as ABS, appropriately increasing the heatbed temperature can reduce the " -#~ "probability of warping." -#~ msgstr "" -#~ "Verwerfungen vermeiden\n" -#~ "Wussten Sie, dass beim Drucken von Materialien, die zu Verwerfungen " -#~ "neigen, wie z.B. ABS, durch eine entsprechende Erhöhung der " -#~ "Heizbetttemperatur die Wahrscheinlichkeit von Verwerfungen verringert " -#~ "werden kann." - #~ msgid "wiki" #~ msgstr "wiki" diff --git a/localization/i18n/fr/OrcaSlicer_fr.po b/localization/i18n/fr/OrcaSlicer_fr.po index 6a8000775e..3467e433d2 100644 --- a/localization/i18n/fr/OrcaSlicer_fr.po +++ b/localization/i18n/fr/OrcaSlicer_fr.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: Orca Slicer\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-01-13 17:34+0100\n" +"POT-Creation-Date: 2024-01-21 14:28+0100\n" "PO-Revision-Date: \n" "Last-Translator: \n" "Language-Team: Guislain Cyril, Thomas Lété\n" @@ -759,7 +759,7 @@ msgstr "Annuler les modifications apportées à la police." #, boost-format msgid "Font \"%1%\" can't be selected." -msgstr "La police « %1% » ne peut pas être sélectionnée." +msgstr "La police « %1% » ne peut pas être sélectionnée." msgid "Operation" msgstr "Opération" @@ -845,7 +845,7 @@ msgstr "Impossible de supprimer le dernier style existant." #, boost-format msgid "Are you sure you want to permanently remove the \"%1%\" style?" -msgstr "Êtes-vous sûr de vouloir supprimer définitivement le style « %1% » ?" +msgstr "Êtes-vous sûr de vouloir supprimer définitivement le style « %1% » ?" #, boost-format msgid "Delete \"%1%\" style." @@ -1015,8 +1015,8 @@ msgid "" "Can't load exactly same font(\"%1%\"). Aplication selected a similar " "one(\"%2%\"). You have to specify font for enable edit text." msgstr "" -"Impossible de charger exactement la même police (« %1% »). L’application a " -"sélectionné une police similaire (« %2% »). Vous devez spécifier la police " +"Impossible de charger exactement la même police (« %1% »). L’application a " +"sélectionné une police similaire (« %2% »). Vous devez spécifier la police " "pour permettre l’édition du texte." msgid "No symbol" @@ -2995,8 +2995,8 @@ msgid "" "A desiccant status lower than two bars indicates that desiccant may be " "inactive. Please change the desiccant.(The bars: higher the better.)" msgstr "" -"Un état du dessicant inférieur à deux barres indique que le dessicant est " -"peut-être inactif. Veuillez changer le déshydratant. (Plus c'est élevé, " +"Un état du dessicateur inférieur à deux barres indique que le dessicateur " +"est peut-être inactif. Veuillez changer le déshydratant. (Plus c'est élevé, " "mieux c'est.)" msgid "" @@ -3005,7 +3005,7 @@ msgid "" "process. During this time, the indicator may not represent the chamber " "accurately." msgstr "" -"Remarque: Lorsque le couvercle est ouvert ou que le sachet de dessinateur " +"Remarque: Lorsque le couvercle est ouvert ou que le sachet de dessicateur " "est changé, cela peut prendre plusieurs heures ou une nuit pour absorber " "l'humidité. Les basses températures ralentissent également le processus. " "Pendant ce temps, l'indicateur pourrait ne pas représenter l'humidité dans " @@ -3423,8 +3423,8 @@ msgid "" "Alternate extra wall only works with ensure vertical shell thickness " "disabled. " msgstr "" -"La paroi supplémentaire alternée ne fonctionne que si « Assurer l’épaisseur " -"verticale de la coque » est désactivé. " +"La paroi supplémentaire alternée ne fonctionne que si « Assurer l’épaisseur " +"verticale de la coque » est désactivé. " msgid "" "Change these settings automatically? \n" @@ -3433,9 +3433,9 @@ msgid "" "No - Dont use alternate extra wall" msgstr "" "Modifier ces paramètres automatiquement ? \n" -"Oui - Désactiver « Assurer l’épaisseur verticale de la coque » et activer " -"« Paroi supplémentaire alternée »\n" -"Non - Ne pas utiliser « Paroi supplémentaire alternée »" +"Oui - Désactiver « Assurer l’épaisseur verticale de la coque » et activer « " +"Paroi supplémentaire alternée »\n" +"Non - Ne pas utiliser « Paroi supplémentaire alternée »" msgid "" "Prime tower does not work when Adaptive Layer Height or Independent Support " @@ -4148,6 +4148,15 @@ msgstr "Passer en LIVE" msgid "Resolution" msgstr "Résolution" +msgid "Enable" +msgstr "Activer" + +msgid "Hostname or IP" +msgstr "Nom d’hôte ou IP" + +msgid "Custom camera source" +msgstr "Source caméra personnalisée" + msgid "Show \"Live Video\" guide page." msgstr "Afficher la page de guide « Vidéo en direct »." @@ -4968,6 +4977,9 @@ msgstr "Carte SD" msgid "Camera Setting" msgstr "Réglage de la Caméra" +msgid "Switch Camera View" +msgstr "Changer la vue de la caméra" + msgid "Control" msgstr "Contrôle" @@ -6591,7 +6603,7 @@ msgid "Busy" msgstr "Occupé" msgid "Bambu Cool Plate" -msgstr "Plaque Bambu Cool Plate" +msgstr "Plateau Cool Plate" msgid "PLA Plate" msgstr "Plaque PLA" @@ -6603,7 +6615,7 @@ msgid "Bambu Smooth PEI Plate" msgstr "Bambu Smooth PEI Plate" msgid "High temperature Plate" -msgstr "Bambu High Temperature Plate" +msgstr "Plateau haute température" msgid "Bambu Textured PEI Plate" msgstr "Bambu Textured PEI Plate" @@ -6827,8 +6839,8 @@ msgid "" "Caution to use! Flow calibration on Textured PEI Plate may fail due to the " "scattered surface." msgstr "" -"Attention à l’utilisation ! La calibration du débit sur le plateau Bambu " -"Dual-Sided Textured PEI peut échouer en raison de la surface texturée." +"Attention à l’utilisation ! La calibration du débit sur le plateau PEI " +"texturé double face peut échouer en raison de la surface texturée." msgid "Automatic flow calibration using Micro Lidar" msgstr "Calibration automatique du débit à l’aide du Micro-Lidar" @@ -7112,6 +7124,10 @@ msgstr "Générateur de paroi" msgid "Walls and surfaces" msgstr "Parois et surfaces" +msgid "Small Area Infill Flow Compensation (experimental)" +msgstr "" +"Compensation des débits de remplissage des petites zones (expérimental)" + msgid "Bridging" msgstr "Ponts" @@ -7258,17 +7274,16 @@ msgstr "" "sur le plateau Engineering." msgid "Smooth PEI Plate / High Temp Plate" -msgstr "Bambu Smooth PEI Plate / High Temp Plate" +msgstr "Plateau PEI lisse / Plateau haute température" msgid "" "Bed temperature when Smooth PEI Plate/High temperature plate is installed. " "Value 0 means the filament does not support to print on the Smooth PEI Plate/" "High Temp Plate" msgstr "" -"Température du plateau lorsque le plateau Bambu Smooth PEI Plate/High " -"Temperature Plate est installé. Une valeur à 0 signifie que le filament ne " -"prend pas en charge l'impression sur le plateau Bambu Smooth PEI Plate/High " -"Temperature Plate" +"Température du plateau lorsque le Plateau PEI lisse / haute température est " +"installé. Une valeur à 0 signifie que le filament ne prend pas en charge " +"l'impression sur le plateau PEI lisse/haute température" msgid "Textured PEI Plate" msgstr "Plaque PEI texturée" @@ -8564,7 +8579,7 @@ msgid "" "when prime tower is enabled." msgstr "" "L’utilisation de diamètres de buses et de filaments différents n’est pas " -"autorisée lorsque l’option « prime tower » est activée." +"autorisée lorsque l’option « prime tower » est activée." msgid "" "The Wipe Tower is currently only supported with the relative extruder " @@ -9011,6 +9026,39 @@ msgstr "" "que l'épaisseur de la coque inférieure est absolument déterminée par les " "couches de la coque inférieure" +msgid "Apply gap fill" +msgstr "Remplissage des trous" + +msgid "" +"Enables gap fill for the selected surfaces. The minimum gap length that will " +"be filled can be controlled from the filter out tiny gaps option below.\n" +"\n" +"Options:\n" +"1. Everywhere: Applies gap fill to top, bottom and internal solid surfaces\n" +"2. Top and Bottom surfaces: Applies gap fill to top and bottom surfaces " +"only\n" +"3. Nowhere: Disables gap fill\n" +msgstr "" +"Active le remplissage des trous pour les surfaces sélectionnées. La longueur " +"minimale du trou qui sera comblé peut être contrôlée à l’aide de l’option " +"« Filtrer les petits trous » ci-dessous.\n" +"\n" +"Options :\n" +"1. Partout : Applique le remplissage des trous aux surfaces solides " +"supérieures, inférieures et internes.\n" +"2. Surfaces supérieure et inférieure : Remplissage des trous uniquement sur " +"les surfaces supérieures et inférieures.\n" +"3. Nulle part : Désactive le remplissage des trous\n" + +msgid "Everywhere" +msgstr "Partout" + +msgid "Top and bottom surfaces" +msgstr "Surfaces supérieure et inférieure" + +msgid "Nowhere" +msgstr "Nulle part" + msgid "Force cooling for overhang and bridge" msgstr "Forcer la ventilation pour les surplombs et ponts" @@ -9150,7 +9198,7 @@ msgstr "" "Si une surface supérieure doit être imprimée et qu’elle est partiellement " "couverte par une autre couche, elle ne sera pas considérée comme une couche " "supérieure si sa largeur est inférieure à cette valeur. Cela peut être utile " -"pour ne pas déclencher l’option « un périmètre sur le dessus » sur des " +"pour ne pas déclencher l’option « un périmètre sur le dessus » sur des " "surfaces qui ne devraient être couvertes que par des périmètres. Cette " "valeur peut être un mm ou un % de la largeur d’extrusion du périmètre.\n" "Attention : Si cette option est activée, des artefacts peuvent être créés si " @@ -9376,6 +9424,15 @@ msgstr "Par couche" msgid "By object" msgstr "Par objet" +msgid "Layer order" +msgstr "Ordre des couches" + +msgid "Print order within a single layer" +msgstr "Ordre d’impression au sein d’une même couche" + +msgid "As object list" +msgstr "En tant que liste d’objets" + msgid "Slow printing down for better layer cooling" msgstr "Impression lente pour un meilleur refroidissement des couches" @@ -9596,6 +9653,25 @@ msgstr "" "garantir l'épaisseur verticale de la coque (couches solides " "supérieure+inférieure)." +msgid "Further reduce solid infill on walls (experimental)" +msgstr "Réduire davantage le remplissage solide des parois (expérimental)" + +msgid "" +"Further reduces any solid infill applied to walls. As there will be very " +"limited infill supporting solid surfaces, make sure that you are using " +"adequate number of walls to support the part on sloping surfaces.\n" +"\n" +"For heavily sloped surfaces this option is not suitable as it will generate " +"too thin of a top layer and should be disabled." +msgstr "" +"Réduit encore davantage les remplissages solides appliqués aux parois. Étant " +"donné que le remplissage des surfaces solides sera très limité, assurez-vous " +"que vous utilisez un nombre suffisant de parois pour soutenir la partie sur " +"les surfaces inclinées.\n" +"\n" +"Pour les surfaces fortement inclinées, cette option n’est pas adaptée car " +"elle génère une couche supérieure trop fine et doit être désactivée." + msgid "Top surface pattern" msgstr "Motif de surface supérieure" @@ -10887,6 +10963,28 @@ msgstr "" msgid "This G-code will be used as a custom code" msgstr "Ce G-code sera utilisé comme code personnalisé" +msgid "Enable Flow Compensation" +msgstr "Activer la compensation de débit" + +msgid "Enable flow compensation for small infill areas" +msgstr "" +"Activer la compensation des débits pour les petites zones de remplissage" + +msgid "Flow Compensation Model" +msgstr "Modèle de compensation de débit" + +msgid "" +"Flow Compensation Model, used to adjust the flow for small infill areas. The " +"model is expressed as a comma separated pair of values for extrusion length " +"and flow correction factors, one per line, in the following format: " +"\"1.234,5.678\"" +msgstr "" +"Modèle de compensation du débit, utilisé pour ajuster le débit pour les " +"petites zones de remplissage. Le modèle est exprimé sous la forme d’une " +"paire de valeurs séparées par des virgules pour la longueur d’extrusion et " +"les facteurs de correction du débit, une par ligne, dans le format suivant : " +"« 1.234,5.678 »" + msgid "Maximum speed X" msgstr "Vitesse maximale X" @@ -11246,9 +11344,6 @@ msgstr "" "peut réduire les rétractions pour les modèles complexes et économiser du " "temps d’impression, mais ralentit la découpe et la génération du G-code." -msgid "Enable" -msgstr "Activer" - msgid "Filename format" msgstr "Format du nom de fichier" @@ -11332,8 +11427,8 @@ msgstr "" "manière, le remplissage est coincé verticalement entre les parois, ce qui " "permet d’obtenir des impressions plus solides. \n" "\n" -"Lorsque cette option est activée, l’option « assurer l’épaisseur verticale " -"de la coque » doit être désactivée. \n" +"Lorsque cette option est activée, l’option « assurer l’épaisseur verticale " +"de la coque » doit être désactivée. \n" "\n" "Il n’est pas recommandé d’utiliser le remplissage par éclairs avec cette " "option, car il y a peu de remplissage pour ancrer les périmètres " @@ -11461,7 +11556,7 @@ msgid "" "parameter: \"Z hop upper boundary\"" msgstr "" "Le saut de Z ne sera effectif que si Z est supérieur à cette valeur et " -"inférieur au paramètre : « Limite supérieure du saut de Z »" +"inférieur au paramètre : « Limite supérieure du saut de Z »" msgid "Z hop upper boundary" msgstr "Limite supérieure du saut de Z" @@ -11471,7 +11566,7 @@ msgid "" "the parameter: \"Z hop lower boundary\" and is below this value" msgstr "" "Si cette valeur est positive, le saut de Z ne sera effectif que si Z est " -"supérieur au paramètre : « Limite inférieure de Z hop » et qu’il est " +"supérieur au paramètre : « Limite inférieure de Z hop » et qu’il est " "inférieur à cette valeur." msgid "Z hop type" @@ -11758,7 +11853,7 @@ msgid "" "Smooth Spiral smoothes out X and Y moves as wellresulting in no visible seam " "at all, even in the XY directions on walls that are not vertical" msgstr "" -"« Spirale lisse » lisse également les mouvements X et Y, de sorte qu’aucune " +"« Spirale lisse » lisse également les mouvements X et Y, de sorte qu’aucune " "couture n’est visible, même dans les directions XY sur des parois qui ne " "sont pas verticales." @@ -12649,8 +12744,8 @@ msgid "" "Wipe tower is only compatible with relative mode. It is recommended on most " "printers. Default is checked" msgstr "" -"L’extrusion relative est recommandée lors de l’utilisation de l’option " -"« label_objects ». Certains extrudeurs fonctionnent mieux avec cette option " +"L’extrusion relative est recommandée lors de l’utilisation de l’option « " +"label_objects ». Certains extrudeurs fonctionnent mieux avec cette option " "non verrouillée (mode d’extrusion absolu). La tour d’essuyage n’est " "compatible qu’avec le mode relatif. Il est recommandé sur la plupart des " "imprimantes. L’option par défaut est cochée" @@ -12767,11 +12862,11 @@ msgstr "" "\n" "REMARQUE : les surfaces inférieures et supérieures ne sont pas affectées par " "cette valeur afin d’éviter les lacunes visuelles sur le côté du modèle. " -"Réglez le « seuil d’une paroi » dans les paramètres avancés ci-dessous pour " +"Réglez le « seuil d’une paroi » dans les paramètres avancés ci-dessous pour " "ajuster la sensibilité de ce qui est considéré comme une surface supérieure. " -"Le « seuil d’une paroi » n’est visible que si ce paramètre est supérieur à " -"la valeur par défaut de 0,5 ou si l’option « surfaces supérieures à une " -"paroi » est activée." +"Le « seuil d’une paroi » n’est visible que si ce paramètre est supérieur à " +"la valeur par défaut de 0,5 ou si l’option « surfaces supérieures à une " +"paroi » est activée." msgid "First layer minimum wall width" msgstr "Largeur minimale de la paroi de la première couche" @@ -13644,11 +13739,9 @@ msgstr "Filament" msgid "Start temp: " msgstr "Temp. de début: " - msgid "End temp: " msgstr "Temp. de fin: " - msgid "Temp step: " msgstr "Intervalle de temp. : " @@ -13946,7 +14039,7 @@ msgstr "" msgid "" "\"Bambu\" or \"Generic\" can not be used as a Vendor for custom filaments." msgstr "" -"« Bambu » ou « Générique » ne peuvent pas être utilisés comme fournisseur de " +"« Bambu » ou « Générique » ne peuvent pas être utilisés comme fournisseur de " "filaments personnalisés." msgid "Filament type is not selected, please reselect type." @@ -13993,10 +14086,10 @@ msgstr "" msgid "" "We would rename the presets as \"Vendor Type Serial @printer you " "selected\". \n" -"To add preset for more prinetrs, Please go to printer selection" +"To add preset for more printers, Please go to printer selection" msgstr "" -"Nous renommerions les préréglages en « Fournisseur Type Série @imprimante " -"que vous avez sélectionnée ». \n" +"Nous renommerions les préréglages en « Vendor Type Serial @printer you " +"selected ». \n" "Pour ajouter des préréglages pour d’autres imprimantes, veuillez aller à la " "sélection de l’imprimante." @@ -14112,7 +14205,7 @@ msgid "" "You have entered an illegal input in the printable area section on the first " "page. Please check before creating it." msgstr "" -"Vous avez introduit une donnée illégale dans la section « zone imprimable » " +"Vous avez introduit une donnée illégale dans la section « zone imprimable » " "de la première page. Veuillez vérifier avant de la créer." msgid "The custom printer or model is not inputed, place input." @@ -14578,7 +14671,7 @@ msgid "" "Message body: \"%2%\"" msgstr "" "Statut HTTP : %1%\n" -"Corps du message : « %2% »" +"Corps du message : « %2% »" #, boost-format msgid "" @@ -14587,8 +14680,8 @@ msgid "" "Error: \"%2%\"" msgstr "" "L’analyse de la réponse de l’hôte a échoué.\n" -"Corps du message : « %1% »\n" -"Erreur : « %2% »" +"Corps du message : « %1% »\n" +"Erreur : « %2% »" #, boost-format msgid "" @@ -14597,8 +14690,21 @@ msgid "" "Error: \"%2%\"" msgstr "" "L’énumération des imprimantes hôtes a échoué.\n" -"Corps du message : « %1% »\n" -"Erreur : « %2% »" +"Corps du message : « %1% »\n" +"Erreur : « %2% »" + +#~ msgid "End end: " +#~ msgstr "Temp. de fin: " + +#~ msgid "" +#~ "We would rename the presets as \"Vendor Type Serial @printer you " +#~ "selected\". \n" +#~ "To add preset for more prinetrs, Please go to printer selection" +#~ msgstr "" +#~ "Nous renommerions les préréglages en « Fournisseur Type Série @imprimante " +#~ "que vous avez sélectionnée ». \n" +#~ "Pour ajouter des préréglages pour d’autres imprimantes, veuillez aller à " +#~ "la sélection de l’imprimante." #~ msgid "The Config can not be loaded." #~ msgstr "La configuration ne peut pas être chargée." diff --git a/resources/web/data/text.js b/resources/web/data/text.js index a5dd7375ba..94483e517d 100644 --- a/resources/web/data/text.js +++ b/resources/web/data/text.js @@ -84,9 +84,21 @@ var LangText = { t89: "Open Containing Folder", t90: "3D Model", t91: "Download 3D models", - t92: "Bambu Christmas Cabin", - t93: "Printer Connection", - t94: "Please set up your printer connection to view the device.", + "t92": "Create by", + "t93": "Remixed by", + "t94": "Shared by", + "t95": "Model Information", + "t96": "Accessories", + "t97": "Profile Information", + "t98": "Model name", + "t100":"Model description", + "t101":"BOM", + "t102":"Assembly Guide", + "t103":"Other", + "t104":"Profile name", + "t105":"Profile Author", + "t106":"Profile description", + orca1: "Edit Project Info", }, es_ES: { t1: "Bienvenido a Orca Slicer", @@ -173,9 +185,20 @@ var LangText = { t89: "Abrir carpeta contenedora", t90: "Modelo 3D", t91: "Descargar modelos 3D", - t92: "Cabina Bambú de Navidad", - t93: "Conexión de Impresora", - t94: "Por favor, configure la conexión de red de la impresora para encontrarla.", + "t92": "Creado por", + "t93": "Remixado por", + "t94": "Compartido por", + "t95": "Información del modelo", + "t96": "Accesorios", + "t97": "Información del perfil", + "t98": "Nombre del modelo", + "t100": "Descripción del modelo", + "t101": "Lista de materiales", + "t102": "Guía de ensamblaje", + "t103": "Otros", + "t104": "Nombre del perfil", + "t105": "Autor del perfil", + "t106": "Descripción del perfil", }, de_DE: { t1: "Willkommen im Orca Slicer", @@ -262,7 +285,20 @@ var LangText = { t89: "Enthaltenden Ordner öffnen", t90: "3D-Modell", t91: "3D-Modelle herunterladen", - t92: "Bambu Weihnachtshütte", + "t92": "Erstellt von", + "t93": "Remixed von", + "t94": "Geteilt von", + "t95": "Modellinformationen", + "t96": "Zubehör", + "t97": "Profilinformationen", + "t98": "Modellname", + "t100": "Modellbeschreibung", + "t101": "Stückliste", + "t102": "Montageanleitung", + "t103": "Andere", + "t104": "Profilname", + "t105": "Profilautor", + "t106": "Profilbeschreibung", }, cs_CZ: { t1: "Vítejte v Orca Slicer", @@ -349,7 +385,20 @@ var LangText = { t89: "Otevřít složku obsahující", t90: "3D model", t91: "Stáhnout 3D modely", - t92: "Vánoční kabina Bambu", + "t92": "Vytvořil", + "t93": "Přepracováno", + "t94": "Sdíleno", + "t95": "Informace o modelu", + "t96": "Příslušenství", + "t97": "Informace o profilu", + "t98": "Název modelu", + "t100":"Popis modelu", + "t101":"Seznam součástek (BOM)", + "t102":"Průvodce sestavením", + "t103":"Jiné", + "t104":"Název profilu", + "t105":"Autor profilu", + "t106":"Popis profilu", }, fr_FR: { t1: "Bienvenue sur Orca Slicer", @@ -436,9 +485,20 @@ var LangText = { t89: "Ouvrir le dossier contenant", t90: "Modèle 3D", t91: "Télécharger des modèles 3D", - t92: "Cabane de Noël Bambu", - t93: "Connexion à l'imprimante", - t94: "Veuillez configurer la connexion de votre imprimante pour afficher l'interface.", + "t92": "Créé par", + "t93": "Remixé par", + "t94": "Partagé par", + "t95": "Informations sur le modèle", + "t96": "Accessoires", + "t97": "Informations de profil", + "t98": "Nom du modèle", + "t100": "Description du modèle", + "t101": "BOM", + "t102": "Guide d'assemblage", + "t103": "Autre", + "t104": "Nom du profil", + "t105": "Auteur du profil", + "t106": "Description du profil", t109: "Filaments du système", t110: "Filaments personnalisés", t111: "Créer un nouveau filament", @@ -544,7 +604,20 @@ var LangText = { t89: "打开所在的文件夹", t90: "3D 模型", t91: "下载3D模型", - t92: "Bambu圣诞小屋", + "t92": "创作", + "t93": "修改", + "t94": "分享", + "t95": "模型信息", + "t96": "附件", + "t97": "配置信息", + "t98": "模型名称", + "t100":"模型介绍", + "t101":"物料清单", + "t102":"装备指导", + "t103":"其他", + "t104":"配置名称", + "t105":"配置作者", + "t106":"配置介绍", wk1: "快速入门指南", wk2: "本文介绍了Orca Slicer的最基本用法。它指导用户配置软件,创建项目,并逐步完成第一个打印任务。", wk3: "基于项目的工作流", @@ -561,6 +634,7 @@ var LangText = { wk14: "与STL相比,STEP带来了更多有效的信息。由于STEP的高精度,切片时可以生成更多的圆弧路径。STEP还包括模型每个零件的装配关系,可分割模型后恢复装配视图。", wk15: "3D文本", wk16: "使用3D文本工具,用户可以轻松地在项目中创建各种3D文本形状,使模型更加个性化。Orca Slicer提供了数十种字体,并支持粗体和斜体样式,使文本具有更大的灵活性。", + orca1: "编辑项目信息", }, zh_TW: { t1: "歡迎使用 Orca Slicer", diff --git a/resources/web/model/css/dark.css b/resources/web/model/css/dark.css index 6e7e12212f..e6ee245e38 100644 --- a/resources/web/model/css/dark.css +++ b/resources/web/model/css/dark.css @@ -65,4 +65,9 @@ a .FileItem { background-color:#36363C; -} \ No newline at end of file +} + +#AddModelInfoBtn:hover +{ + color: #000; +} diff --git a/resources/web/model/img/edit.svg b/resources/web/model/img/edit.svg new file mode 100644 index 0000000000..ac5e0f35e5 --- /dev/null +++ b/resources/web/model/img/edit.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/web/model/index.html b/resources/web/model/index.html index 739f6d4451..6b091afa6b 100644 --- a/resources/web/model/index.html +++ b/resources/web/model/index.html @@ -26,6 +26,7 @@
no model information
+
Edit Project Info
@@ -42,6 +43,9 @@
Profile Information
+
+ Edit Project Info +
 
diff --git a/resources/web/model/model.css b/resources/web/model/model.css index 25aba5201e..b3bfac604c 100644 --- a/resources/web/model/model.css +++ b/resources/web/model/model.css @@ -153,7 +153,7 @@ body position:fixed; top: 24px; width: 264px; - height: 120px; + height: 160px; flex-shrink: 0; } @@ -376,3 +376,19 @@ body background-color: rgba(255,0,0,.5)!important; } +#AddModelInfoBtn +{ + border-width: 1px; + border-style: solid; + padding: 0px 10px; + border-radius: 6px; + line-height: 26px; + height: 26px; + margin-top: 20px; + cursor: pointer; +} + +#AddModelInfoBtn:hover +{ + background-color:#CDCECE; +} diff --git a/resources/web/model/model.js b/resources/web/model/model.js index 73958122a4..30bbdce678 100644 --- a/resources/web/model/model.js +++ b/resources/web/model/model.js @@ -580,7 +580,14 @@ function OnClickOpenImage( F_ID ) $("img#"+F_ID).click(); } - +function OnClickEditProjectInfo() +{ + var tSend={}; + tSend['sequence_id']=Math.round(new Date() / 1000); + tSend['command']="edit_project_info"; + + SendWXMessage( JSON.stringify(tSend) ); +} diff --git a/src/libslic3r/CMakeLists.txt b/src/libslic3r/CMakeLists.txt index 02d935f6e6..ebabfab426 100644 --- a/src/libslic3r/CMakeLists.txt +++ b/src/libslic3r/CMakeLists.txt @@ -157,6 +157,8 @@ set(lisbslic3r_sources GCode/PrintExtents.hpp GCode/RetractWhenCrossingPerimeters.cpp GCode/RetractWhenCrossingPerimeters.hpp + GCode/SmallAreaInfillFlowCompensator.cpp + GCode/SmallAreaInfillFlowCompensator.hpp GCode/SpiralVase.cpp GCode/SpiralVase.hpp GCode/SeamPlacer.cpp diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 157a4c53be..28a53c9429 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -1849,6 +1849,15 @@ static inline std::vector sort_object_instances_by_max_z(c //BBS: add sort logic for seq-print std::vector sort_object_instances_by_model_order(const Print& print, bool init_order) { + auto find_object_index = [](const Model& model, const ModelObject* obj) { + for (int index = 0; index < model.objects.size(); index++) + { + if (model.objects[index] == obj) + return index; + } + return -1; + }; + // Build up map from ModelInstance* to PrintInstance* std::vector> model_instance_to_print_instance; model_instance_to_print_instance.reserve(print.num_object_instances()); @@ -1856,10 +1865,16 @@ std::vector sort_object_instances_by_model_order(const Pri for (const PrintInstance &print_instance : print_object->instances()) { if (init_order) - const_cast(print_instance.model_instance)->arrange_order = print_instance.model_instance->id().id; + const_cast(print_instance.model_instance)->arrange_order = find_object_index(print.model(), print_object->model_object()); model_instance_to_print_instance.emplace_back(print_instance.model_instance, &print_instance); } std::sort(model_instance_to_print_instance.begin(), model_instance_to_print_instance.end(), [](auto &l, auto &r) { return l.first->arrange_order < r.first->arrange_order; }); + if (init_order) { + // Re-assign the arrange_order so each instance has a unique order number + for (int k = 0; k < model_instance_to_print_instance.size(); k++) { + const_cast(model_instance_to_print_instance[k].first)->arrange_order = k + 1; + } + } std::vector instances; instances.reserve(model_instance_to_print_instance.size()); @@ -1980,6 +1995,9 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato } else m_enable_extrusion_role_markers = false; + if (!print.config().small_area_infill_flow_compensation_model.empty()) + m_small_area_infill_flow_compensator = make_unique(print.config()); + // if thumbnail type of BTT_TFT, insert above header // if not, it is inserted under the header in its normal spot const GCodeThumbnailsFormat m_gcode_thumbnail_format = print.full_print_config().opt_enum("thumbnails_format"); @@ -2215,8 +2233,11 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato // In non-sequential print, the printing extruders may have been modified by the extruder switches stored in Model::custom_gcode_per_print_z. // Therefore initialize the printing extruders from there. this->set_extruders(tool_ordering.all_extruders()); - // Order object instances using a nearest neighbor search. - print_object_instances_ordering = chain_print_object_instances(print); + print_object_instances_ordering = + // By default, order object instances using a nearest neighbor search. + print.config().print_order == PrintOrder::Default ? chain_print_object_instances(print) + // Otherwise same order as the object list + : sort_object_instances_by_model_order(print); } if (initial_extruder_id == (unsigned int)-1) { // Nothing to print! @@ -2540,9 +2561,7 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato // another one, set first layer temperatures. This happens before the Z move // is triggered, so machine has more time to reach such temperatures. this->placeholder_parser().set("current_object_idx", int(finished_objects)); - //BBS: remove printing_by_object_gcode - //std::string printing_by_object_gcode = this->placeholder_parser_process("printing_by_object_gcode", print.config().printing_by_object_gcode.value, initial_extruder_id); - std::string printing_by_object_gcode; + std::string printing_by_object_gcode = this->placeholder_parser_process("printing_by_object_gcode", print.config().printing_by_object_gcode.value, initial_extruder_id); // Set first layer bed and extruder temperatures, don't wait for it to reach the temperature. this->_print_first_layer_bed_temperature(file, print, printing_by_object_gcode, initial_extruder_id, false); this->_print_first_layer_extruder_temperatures(file, print, printing_by_object_gcode, initial_extruder_id, false); @@ -4020,7 +4039,7 @@ LayerResult GCode::process_layer( std::vector instances_to_print; bool has_prime_tower = print.config().enable_prime_tower && print.extruders().size() > 1 - && (print.config().print_sequence == PrintSequence::ByLayer + && ((print.config().print_sequence == PrintSequence::ByLayer && print.config().print_order == PrintOrder::Default) || (print.config().print_sequence == PrintSequence::ByObject && print.objects().size() == 1)); if (has_prime_tower) { int plate_idx = print.get_plate_index(); @@ -5268,15 +5287,25 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description, for (const Line& line : path.polyline.lines()) { const double line_length = line.length() * SCALING_FACTOR; path_length += line_length; + auto dE = e_per_mm * line_length; + if (m_small_area_infill_flow_compensator && m_config.small_area_infill_flow_compensation.value) { + auto oldE = dE; + dE = m_small_area_infill_flow_compensator->modify_flow(line_length, dE, path.role()); + + if (m_config.gcode_comments && oldE > 0 && oldE != dE) { + description += Slic3r::format(" | Old Flow Value: %0.5f Length: %0.5f",oldE, line_length); + } + } gcode += m_writer.extrude_to_xy( this->point_to_gcode(line.b), - e_per_mm * line_length, + dE, GCodeWriter::full_gcode_comment ? description : "", path.is_force_no_extrusion()); } } else { // BBS: start to generate gcode from arc fitting data which includes line and arc const std::vector& fitting_result = path.polyline.fitting_result; for (size_t fitting_index = 0; fitting_index < fitting_result.size(); fitting_index++) { + std::string tempDescription = description; switch (fitting_result[fitting_index].path_type) { case EMovePathType::Linear_move: { size_t start_index = fitting_result[fitting_index].start_point_index; @@ -5285,10 +5314,19 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description, const Line line = Line(path.polyline.points[point_index - 1], path.polyline.points[point_index]); const double line_length = line.length() * SCALING_FACTOR; path_length += line_length; + auto dE = e_per_mm * line_length; + if (m_small_area_infill_flow_compensator && m_config.small_area_infill_flow_compensation.value) { + auto oldE = dE; + dE = m_small_area_infill_flow_compensator->modify_flow(line_length, dE, path.role()); + + if (m_config.gcode_comments && oldE > 0 && oldE != dE) { + tempDescription += Slic3r::format(" | Old Flow Value: %0.5f Length: %0.5f",oldE, line_length); + } + } gcode += m_writer.extrude_to_xy( this->point_to_gcode(line.b), - e_per_mm * line_length, - GCodeWriter::full_gcode_comment ? description : "", path.is_force_no_extrusion()); + dE, + GCodeWriter::full_gcode_comment ? tempDescription : "", path.is_force_no_extrusion()); } break; } @@ -5298,12 +5336,21 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description, const double arc_length = fitting_result[fitting_index].arc_data.length * SCALING_FACTOR; const Vec2d center_offset = this->point_to_gcode(arc.center) - this->point_to_gcode(arc.start_point); path_length += arc_length; + auto dE = e_per_mm * arc_length; + if (m_small_area_infill_flow_compensator && m_config.small_area_infill_flow_compensation.value) { + auto oldE = dE; + dE = m_small_area_infill_flow_compensator->modify_flow(arc_length, dE, path.role()); + + if (m_config.gcode_comments && oldE > 0 && oldE != dE) { + tempDescription += Slic3r::format(" | Old Flow Value: %0.5f Length: %0.5f",oldE, arc_length); + } + } gcode += m_writer.extrude_arc_to_xy( this->point_to_gcode(arc.end_point), center_offset, - e_per_mm * arc_length, + dE, arc.direction == ArcDirection::Arc_Dir_CCW, - GCodeWriter::full_gcode_comment ? description : "", path.is_force_no_extrusion()); + GCodeWriter::full_gcode_comment ? tempDescription : "", path.is_force_no_extrusion()); break; } default: @@ -5325,6 +5372,7 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description, pre_fan_enabled = check_overhang_fan(new_points[0].overlap, path.role()); for (size_t i = 1; i < new_points.size(); i++) { + std::string tempDescription = description; const ProcessedPoint &processed_point = new_points[i]; const ProcessedPoint &pre_processed_point = new_points[i-1]; Vec2d p = this->point_to_gcode_quantized(processed_point.p); @@ -5363,8 +5411,17 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description, gcode += m_writer.set_speed(new_speed, "", comment); last_set_speed = new_speed; } + auto dE = e_per_mm * line_length; + if (m_small_area_infill_flow_compensator && m_config.small_area_infill_flow_compensation.value) { + auto oldE = dE; + dE = m_small_area_infill_flow_compensator->modify_flow(line_length, dE, path.role()); + + if (m_config.gcode_comments && oldE > 0 && oldE != dE) { + tempDescription += Slic3r::format(" | Old Flow Value: %0.5f Length: %0.5f",oldE, line_length); + } + } gcode += - m_writer.extrude_to_xy(p, e_per_mm * line_length, GCodeWriter::full_gcode_comment ? description : ""); + m_writer.extrude_to_xy(p, dE, GCodeWriter::full_gcode_comment ? tempDescription : ""); prev = p; diff --git a/src/libslic3r/GCode.hpp b/src/libslic3r/GCode.hpp index 79a97abc70..2260920dc7 100644 --- a/src/libslic3r/GCode.hpp +++ b/src/libslic3r/GCode.hpp @@ -23,6 +23,7 @@ #include "GCode/ExtrusionProcessor.hpp" #include "GCode/PressureEqualizer.hpp" +#include "GCode/SmallAreaInfillFlowCompensator.hpp" #include #include @@ -536,6 +537,8 @@ private: std::unique_ptr m_wipe_tower; + std::unique_ptr m_small_area_infill_flow_compensator; + // Heights (print_z) at which the skirt has already been extruded. std::vector m_skirt_done; // Has the brim been extruded already? Brim is being extruded only for the first object of a multi-object print. @@ -598,6 +601,7 @@ private: friend class WipeTowerIntegration; friend class PressureEqualizer; friend class Print; + friend class SmallAreaInfillFlowCompensator; }; std::vector sort_object_instances_by_model_order(const Print& print, bool init_order = false); diff --git a/src/libslic3r/GCode/SmallAreaInfillFlowCompensator.cpp b/src/libslic3r/GCode/SmallAreaInfillFlowCompensator.cpp new file mode 100644 index 0000000000..573347d5ec --- /dev/null +++ b/src/libslic3r/GCode/SmallAreaInfillFlowCompensator.cpp @@ -0,0 +1,88 @@ +// Modify the flow of extrusion lines inversely proportional to the length of +// the extrusion line. When infill lines get shorter the flow rate will auto- +// matically be reduced to mitigate the effect of small infill areas being +// over-extruded. + +// Based on original work by Alexander Þór licensed under the GPLv3: +// https://github.com/Alexander-T-Moss/Small-Area-Flow-Comp + +#include +#include +#include + +#include "../libslic3r.h" +#include "../PrintConfig.hpp" + +#include "SmallAreaInfillFlowCompensator.hpp" + +namespace Slic3r { + +bool nearly_equal(double a, double b) +{ + return std::nextafter(a, std::numeric_limits::lowest()) <= b && std::nextafter(a, std::numeric_limits::max()) >= b; +} + +SmallAreaInfillFlowCompensator::SmallAreaInfillFlowCompensator(const Slic3r::GCodeConfig& config) +{ + for (auto& line : config.small_area_infill_flow_compensation_model.values) { + std::istringstream iss(line); + std::string value_str; + double eLength = 0.0; + + if (std::getline(iss, value_str, ',')) { + try { + eLength = std::stod(value_str); + if (std::getline(iss, value_str, ',')) { + eLengths.push_back(eLength); + flowComps.push_back(std::stod(value_str)); + } + } catch (...) { + std::stringstream ss; + ss << "Error parsing data point in small area infill compensation model:" << line << std::endl; + + throw Slic3r::InvalidArgument(ss.str()); + } + } + } + + for (int i = 0; i < eLengths.size(); i++) { + if (i == 0) { + if (!nearly_equal(eLengths[i], 0.0)) { + throw Slic3r::InvalidArgument("First extrusion length for small area infill compensation model must be 0"); + } + } else { + if (nearly_equal(eLengths[i], 0.0)) { + throw Slic3r::InvalidArgument("Only the first extrusion length for small area infill compensation model can be 0"); + } + if (eLengths[i] <= eLengths[i - 1]) { + throw Slic3r::InvalidArgument("Extrusion lengths for subsequent points must be increasing"); + } + } + } + + if (!flowComps.empty() && !nearly_equal(flowComps.back(), 1.0)) { + throw Slic3r::InvalidArgument("Final compensation factor for small area infill flow compensation model must be 1.0"); + } + + flowModel.set_points(eLengths, flowComps); +} + +double SmallAreaInfillFlowCompensator::flow_comp_model(const double line_length) +{ + if (line_length == 0 || line_length > max_modified_length()) { + return 1.0; + } + + return flowModel(line_length); +} + +double SmallAreaInfillFlowCompensator::modify_flow(const double line_length, const double dE, const ExtrusionRole role) +{ + if (role == ExtrusionRole::erSolidInfill || role == ExtrusionRole::erTopSolidInfill || role == ExtrusionRole::erBottomSurface) { + return dE * flow_comp_model(line_length); + } + + return dE; +} + +} // namespace Slic3r diff --git a/src/libslic3r/GCode/SmallAreaInfillFlowCompensator.hpp b/src/libslic3r/GCode/SmallAreaInfillFlowCompensator.hpp new file mode 100644 index 0000000000..7d804c9b47 --- /dev/null +++ b/src/libslic3r/GCode/SmallAreaInfillFlowCompensator.hpp @@ -0,0 +1,35 @@ +#ifndef slic3r_GCode_SmallAreaInfillFlowCompensator_hpp_ +#define slic3r_GCode_SmallAreaInfillFlowCompensator_hpp_ + +#include "../libslic3r.h" +#include "../PrintConfig.hpp" +#include "../ExtrusionEntity.hpp" +#include "spline/spline.h" + +namespace Slic3r { + +class SmallAreaInfillFlowCompensator +{ +public: + SmallAreaInfillFlowCompensator() = delete; + explicit SmallAreaInfillFlowCompensator(const Slic3r::GCodeConfig& config); + ~SmallAreaInfillFlowCompensator() = default; + + double modify_flow(const double line_length, const double dE, const ExtrusionRole role); + +private: + // Model points + std::vector eLengths; + std::vector flowComps; + + // TODO: Cubic Spline + tk::spline flowModel; + + double flow_comp_model(const double line_length); + + double max_modified_length() { return eLengths.back(); } +}; + +} // namespace Slic3r + +#endif /* slic3r_GCode_SmallAreaInfillFlowCompensator_hpp_ */ diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index afb7ab8598..ed3624dce8 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -836,7 +836,7 @@ end: // BBS: backup all in one dir std::string Model::get_auxiliary_file_temp_path() { - return get_backup_path("/Auxiliaries"); + return get_backup_path("Auxiliaries"); } // BBS: backup dir diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index db675a5193..03d77b0e3c 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -786,7 +786,7 @@ static std::vector s_Preset_print_options { "independent_support_layer_height", "support_angle", "support_interface_top_layers", "support_interface_bottom_layers", "support_interface_pattern", "support_interface_spacing", "support_interface_loop_pattern", - "support_top_z_distance", "support_on_build_plate_only","support_critical_regions_only", "bridge_no_support", "thick_bridges", "thick_internal_bridges","dont_filter_internal_bridges", "max_bridge_length", "print_sequence", "support_remove_small_overhang", + "support_top_z_distance", "support_on_build_plate_only","support_critical_regions_only", "bridge_no_support", "thick_bridges", "thick_internal_bridges","dont_filter_internal_bridges", "max_bridge_length", "print_sequence", "print_order", "support_remove_small_overhang", "filename_format", "wall_filament", "support_bottom_z_distance", "sparse_infill_filament", "solid_infill_filament", "support_filament", "support_interface_filament","support_interface_not_for_body", "ooze_prevention", "standby_temperature_delta", "interface_shells", "line_width", "initial_layer_line_width", @@ -817,6 +817,7 @@ static std::vector s_Preset_print_options { "wipe_tower_cone_angle", "wipe_tower_extra_spacing", "wipe_tower_extruder", "wiping_volumes_extruders","wipe_tower_bridging", "single_extruder_multi_material_priming", "wipe_tower_rotation_angle", "tree_support_branch_distance_organic", "tree_support_branch_diameter_organic", "tree_support_branch_angle_organic", "hole_to_polyhole", "hole_to_polyhole_threshold", "hole_to_polyhole_twisted", "mmu_segmented_region_max_width", "mmu_segmented_region_interlocking_depth", + "small_area_infill_flow_compensation", "small_area_infill_flow_compensation_model", }; static std::vector s_Preset_filament_options { diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index d2ca1a3b3a..7993f6a7ba 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -314,6 +314,7 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n //|| opt_key == "resolution" //BBS: when enable arc fitting, we must re-generate perimeter || opt_key == "enable_arc_fitting" + || opt_key == "print_order" || opt_key == "wall_sequence") { osteps.emplace_back(posPerimeters); osteps.emplace_back(posEstimateCurledExtrusions); @@ -1043,6 +1044,7 @@ boost::regex regex_g92e0 { "^[ \\t]*[gG]92[ \\t]*[eE](0(\\.0*)?|\\.0+)[ \\t]*(;. StringObjectException Print::validate(StringObjectException *warning, Polygons* collison_polygons, std::vector>* height_polygons) const { std::vector extruders = this->extruders(); + unsigned int nozzles = m_config.nozzle_diameter.size(); if (m_objects.empty()) return {std::string()}; @@ -1050,7 +1052,7 @@ StringObjectException Print::validate(StringObjectException *warning, Polygons* if (extruders.empty()) return { L("No extrusions under current settings.") }; - if (extruders.size() > 1 && m_config.print_sequence != PrintSequence::ByObject) { + if (nozzles < 2 && extruders.size() > 1 && m_config.print_sequence != PrintSequence::ByObject) { auto ret = check_multi_filament_valid(*this); if (!ret.string.empty()) { diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 7dd68dbb86..792d8815d4 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -195,6 +195,12 @@ static t_config_enum_values s_keys_map_PrintSequence { }; CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(PrintSequence) +static t_config_enum_values s_keys_map_PrintOrder{ + { "default", int(PrintOrder::Default) }, + { "as_obj_list", int(PrintOrder::AsObjectList)}, +}; +CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(PrintOrder) + static t_config_enum_values s_keys_map_SlicingMode { { "regular", int(SlicingMode::Regular) }, { "even_odd", int(SlicingMode::EvenOdd) }, @@ -1171,6 +1177,17 @@ void PrintConfigDef::init_fff_params() def->mode = comSimple; def->set_default_value(new ConfigOptionEnum(PrintSequence::ByLayer)); + def = this->add("print_order", coEnum); + def->label = L("Layer order"); + def->tooltip = L("Print order within a single layer"); + def->enum_keys_map = &ConfigOptionEnum::get_enum_values(); + def->enum_values.push_back("default"); + def->enum_values.push_back("as_obj_list"); + def->enum_labels.push_back(L("Default")); + def->enum_labels.push_back(L("As object list")); + def->mode = comAdvanced; + def->set_default_value(new ConfigOptionEnum(PrintOrder::Default)); + def = this->add("slow_down_for_layer_cooling", coBools); def->label = L("Slow printing down for better layer cooling"); def->tooltip = L("Enable this option to slow printing speed down to make the final layer time not shorter than " @@ -2668,6 +2685,26 @@ def = this->add("filament_loading_speed", coFloats); def->mode = comAdvanced; def->set_default_value(new ConfigOptionString("")); + def = this->add("small_area_infill_flow_compensation", coBool); + def->label = L("Enable Flow Compensation"); + def->tooltip = L("Enable flow compensation for small infill areas"); + def->mode = comAdvanced; + def->set_default_value(new ConfigOptionBool(false)); + + def = this->add("small_area_infill_flow_compensation_model", coStrings); + def->label = L("Flow Compensation Model"); + def->tooltip = L( + "Flow Compensation Model, used to adjust the flow for small infill " + "areas. The model is expressed as a comma separated pair of values for " + "extrusion length and flow correction factors, one per line, in the " + "following format: \"1.234,5.678\""); + def->mode = comAdvanced; + def->gui_flags = "serialized"; + def->multiline = true; + def->full_width = true; + def->height = 15; + def->set_default_value(new ConfigOptionStrings{"0,0", "\n0.2,0.4444", "\n0.4,0.6145", "\n0.6,0.7059", "\n0.8,0.7619", "\n1.5,0.8571", "\n2,0.8889", "\n3,0.9231", "\n5,0.9520", "\n10,1"}); + { struct AxisDefault { std::string name; diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index 6c5b10f806..f894a24ca8 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -106,6 +106,13 @@ enum class PrintSequence { Count, }; +enum class PrintOrder +{ + Default, + AsObjectList, + Count, +}; + enum class SlicingMode { // Regular, applying ClipperLib::pftNonZero rule when creating ExPolygons. @@ -920,6 +927,7 @@ PRINT_CONFIG_CLASS_DEFINE( ((ConfigOptionEnum, wall_sequence)) ((ConfigOptionBool, is_infill_first)) + ((ConfigOptionBool, small_area_infill_flow_compensation)) ) PRINT_CONFIG_CLASS_DEFINE( @@ -1067,6 +1075,8 @@ PRINT_CONFIG_CLASS_DEFINE( ((ConfigOptionBool, enable_filament_ramming)) ((ConfigOptionBool, support_multi_bed_types)) + // Small Area Infill Flow Compensation + ((ConfigOptionStrings, small_area_infill_flow_compensation_model)) ) // This object is mapped to Perl as Slic3r::Config::Print. @@ -1098,6 +1108,7 @@ PRINT_CONFIG_CLASS_DERIVED_DEFINE( ((ConfigOptionInts, overhang_fan_speed)) ((ConfigOptionEnumsGeneric, overhang_fan_threshold)) ((ConfigOptionEnum,print_sequence)) + ((ConfigOptionEnum, print_order)) ((ConfigOptionInts, first_layer_print_sequence)) ((ConfigOptionBools, slow_down_for_layer_cooling)) ((ConfigOptionInts, close_fan_the_first_x_layers)) diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index ce64205aae..d3a206123f 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -928,6 +928,10 @@ bool PrintObject::invalidate_state_by_config_options( || opt_key == "wipe_on_loops" || opt_key == "wipe_speed") { steps.emplace_back(posPerimeters); + } else if ( + opt_key == "small_area_infill_flow_compensation" + || opt_key == "small_area_infill_flow_compensation_model") { + steps.emplace_back(posSlice); } else if (opt_key == "gap_infill_speed" || opt_key == "filter_out_gap_fill" ) { // Return true if gap-fill speed has changed from zero value to non-zero or from non-zero value to zero. diff --git a/src/slic3r/GUI/Auxiliary.cpp b/src/slic3r/GUI/Auxiliary.cpp index c3554bfe5f..aab42f6abd 100644 --- a/src/slic3r/GUI/Auxiliary.cpp +++ b/src/slic3r/GUI/Auxiliary.cpp @@ -33,17 +33,29 @@ wxDEFINE_EVENT(EVT_AUXILIARY_IMPORT, wxCommandEvent); wxDEFINE_EVENT(EVT_AUXILIARY_UPDATE_COVER, wxCommandEvent); wxDEFINE_EVENT(EVT_AUXILIARY_UPDATE_DELETE, wxCommandEvent); wxDEFINE_EVENT(EVT_AUXILIARY_UPDATE_RENAME, wxCommandEvent); +wxDEFINE_EVENT(EVT_AUXILIARY_DONE, wxCommandEvent); const std::vector license_list = { - "BSD License", - "Apache License", - "GPL License", - "LGPL License", - "MIT License", - "CC License" + "", + "CC0", + "BY", + "BY-SA", + "BY-ND", + "BY-NC", + "BY-NC-SA", + "BY-NC-ND", }; +static std::shared_ptr ensure_model_info() +{ + auto& model = wxGetApp().plater()->model(); + if (model.model_info == nullptr) { + model.model_info = std::make_shared(); + } + return model.model_info; +} + AuFile::AuFile(wxWindow *parent, fs::path file_path, wxString file_name, AuxiliaryFolderType type, wxWindowID id, const wxPoint &pos, const wxSize &size, long style) { m_type = type; @@ -344,7 +356,7 @@ void AuFile::on_input_enter(wxCommandEvent &evt) } auto existing = false; - auto dir = m_file_path.branch_path(); + auto dir = m_file_path.parent_path(); auto new_fullname = new_file_name + m_file_path.extension().string(); @@ -454,14 +466,12 @@ void AuFile::on_mouse_left_up(wxMouseEvent &evt) void AuFile::on_set_cover() { - if (wxGetApp().plater()->model().model_info == nullptr) { wxGetApp().plater()->model().model_info = std::make_shared(); } - fs::path path(into_path(m_file_name)); - wxGetApp().plater()->model().model_info->cover_file = path.string(); + ensure_model_info()->cover_file = path.string(); //wxGetApp().plater()->model().model_info->cover_file = m_file_name.ToStdString(); - auto full_path = m_file_path.branch_path(); - auto full_root_path = full_path.branch_path(); + auto full_path = m_file_path.parent_path(); + auto full_root_path = full_path.parent_path(); auto full_root_path_str = encode_path(full_root_path.string().c_str()); auto dir = wxString::Format("%s/.thumbnails", full_root_path_str); @@ -505,8 +515,8 @@ void AuFile::on_set_delete() auto is_fine = fs::remove(bfs_path); if (m_cover) { - auto full_path = m_file_path.branch_path(); - auto full_root_path = full_path.branch_path(); + auto full_path = m_file_path.parent_path(); + auto full_root_path = full_path.parent_path(); auto full_root_path_str = encode_path(full_root_path.string().c_str()); auto dir = wxString::Format("%s/.thumbnails", full_root_path_str); fs::path dir_path(dir.ToStdWstring()); @@ -520,8 +530,11 @@ void AuFile::on_set_delete() if (fs::exists(fs::path(middle_img_path))) { fs::remove(fs::path(middle_img_path)); } } - if (wxGetApp().plater()->model().model_info == nullptr) { wxGetApp().plater()->model().model_info = std::make_shared(); } - if (wxGetApp().plater()->model().model_info->cover_file == m_file_name) { wxGetApp().plater()->model().model_info->cover_file = ""; } + if (wxGetApp().plater()->model().model_info != nullptr) { + if (wxGetApp().plater()->model().model_info->cover_file == m_file_name) { + wxGetApp().plater()->model().model_info->cover_file = ""; + } + } if (is_fine) { auto evt = wxCommandEvent(EVT_AUXILIARY_UPDATE_DELETE); @@ -669,6 +682,7 @@ void AuFolderPanel::update(std::vector paths) } m_gsizer_content->Layout(); Layout(); + Refresh(); } void AuFolderPanel::msw_rescale() @@ -820,9 +834,22 @@ void AuxiliaryPanel::init_bitmap() void AuxiliaryPanel::init_tabpanel() { - auto m_side_tools = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(FromDIP(220), FromDIP(18))); + StateColor btn_bg_green(std::pair(wxColour(206, 206, 206), StateColor::Disabled), + std::pair(wxColour(0, 137, 123), StateColor::Pressed), + std::pair(wxColour(38, 166, 154), StateColor::Hovered), + std::pair(wxColour(0, 150, 136), StateColor::Normal)); + auto back_btn = new Button(this, _L("Back"), "assemble_return", wxBORDER_NONE | wxBU_LEFT | wxBU_EXACTFIT); + back_btn->SetSize(wxSize(FromDIP(220), FromDIP(18))); + back_btn->SetBackgroundColor(btn_bg_green); + back_btn->SetCornerRadius(0); + back_btn->Bind(wxEVT_COMMAND_BUTTON_CLICKED, [this](wxEvent& e) { + auto event = wxCommandEvent(EVT_AUXILIARY_DONE); + event.SetEventObject(m_parent); + wxPostEvent(m_parent, event); + }); + wxBoxSizer *sizer_side_tools = new wxBoxSizer(wxVERTICAL); - sizer_side_tools->Add(m_side_tools, 1, wxEXPAND, 0); + sizer_side_tools->Add(back_btn, 1, wxEXPAND, 0); m_tabpanel = new Tabbook(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, sizer_side_tools, wxNB_LEFT | wxTAB_TRAVERSAL | wxNB_NOPAGETHEME); m_tabpanel->SetBackgroundColour(wxColour("#FEFFFF")); m_tabpanel->Bind(wxEVT_BOOKCTRL_PAGE_CHANGED, [this](wxBookCtrlEvent &e) { ; }); @@ -872,20 +899,7 @@ bool AuxiliaryPanel::Show(bool show) { return wxPanel::Show(show); } void AuxiliaryPanel::init_auxiliary() { Model &model = wxGetApp().plater()->model(); - m_root_dir = encode_path(model.get_auxiliary_file_temp_path().c_str()); - if (wxDirExists(m_root_dir)) { - fs::path path_to_del(m_root_dir.ToStdWstring()); - try { - fs::remove_all(path_to_del); - } catch (...) { - BOOST_LOG_TRIVIAL(error) << "Failed removing the auxiliary directory " << m_root_dir.c_str(); - } - } - - fs::path top_dir_path(m_root_dir.ToStdWstring()); - fs::create_directory(top_dir_path); - - for (auto folder : s_default_folders) create_folder(folder); + Reload(encode_path(model.get_auxiliary_file_temp_path().c_str()), {}); } void AuxiliaryPanel::on_import_file(wxCommandEvent &event) @@ -947,7 +961,7 @@ void AuxiliaryPanel::on_import_file(wxCommandEvent &event) boost::system::error_code ec; - if (!fs::copy_file(src_bfs_path, fs::path(dir_path.ToStdWstring()), fs::copy_option::overwrite_if_exists, ec)) continue; + if (!fs::copy_file(src_bfs_path, fs::path(dir_path.ToStdWstring()), fs::copy_options::overwrite_existing, ec)) continue; Slic3r::put_other_changes(); // add in file list @@ -987,76 +1001,22 @@ std::string AuxiliaryPanel::replaceSpace(std::string s, std::string ts, std::str return s; } -void AuxiliaryPanel::Reload(wxString aux_path) +void AuxiliaryPanel::Reload(wxString aux_path, std::map> paths) { - fs::path new_aux_path(aux_path.ToStdWstring()); - - try { - fs::remove_all(fs::path(m_root_dir.ToStdWstring())); - } catch (...) { - BOOST_LOG_TRIVIAL(error) << "Failed removing the auxiliary directory " << m_root_dir.c_str(); - } - m_root_dir = aux_path; m_paths_list.clear(); - // Check new path. If not exist, create a new one. - if (!fs::exists(new_aux_path)) { - fs::create_directory(new_aux_path); - // Create default folders if they are not loaded - for (auto folder : s_default_folders) { - wxString folder_path = aux_path + "/" + folder; - if (fs::exists(folder_path.ToStdWstring())) continue; - fs::create_directory(folder_path.ToStdWstring()); + + for (const auto & path : paths) { + m_paths_list[path.first] = std::vector{}; + for (const auto & j : path.second) { + m_paths_list[path.first].push_back(j["_filepath"]); } - update_all_panel(); - m_designer_panel->update_info(); - return; - } - - // Load from new path - std::vector dir_cache; - fs::directory_iterator iter_end; - - for (fs::directory_iterator iter(new_aux_path); iter != iter_end; iter++) { - wxString path = iter->path().generic_wstring(); - dir_cache.push_back(iter->path()); - } - - for (auto dir : dir_cache) { - for (fs::directory_iterator iter(dir); iter != iter_end; iter++) { - if (fs::is_directory(iter->path())) continue; - wxString file_path = iter->path().generic_wstring(); - //auto file_path_str = encode_path(file_path.c_str()); - - for (auto folder : s_default_folders) { - auto idx = file_path.find(folder.ToStdString()); - if (idx != std::string::npos) { - auto iter = m_paths_list.find(folder.ToStdString()); - auto file_path_str = fs::path(file_path.ToStdWstring()); - - if (iter != m_paths_list.end()) { - m_paths_list[folder.ToStdString()].push_back(file_path_str); - break; - } else { - m_paths_list[folder.ToStdString()] = std::vector{file_path_str}; - break; - } - } - } - } - } - - // Create default folders if they are not loaded - wxDataViewItemArray default_items; - for (auto folder : s_default_folders) { - wxString folder_path = aux_path + "/" + folder; - if (fs::exists(folder_path.ToStdWstring())) continue; - fs::create_directory(folder_path.ToStdWstring()); } update_all_panel(); update_all_cover(); m_designer_panel->update_info(); + m_tabpanel->SetSelection(0); } void AuxiliaryPanel::update_all_panel() @@ -1121,22 +1081,21 @@ void AuxiliaryPanel::update_all_cover() m_imput_model_name->GetTextCtrl()->SetSize(wxSize(FromDIP(450), -1)); m_sizer_model_name->Add(m_imput_model_name, 0, wxALIGN_CENTER, 0); - /* wxBoxSizer *m_sizer_license = new wxBoxSizer(wxHORIZONTAL); - auto m_text_license = new wxStaticText(this, wxID_ANY, _L("License"), wxDefaultPosition, wxSize(120, -1), 0); + auto m_text_license = new wxStaticText(this, wxID_ANY, _L("License"), wxDefaultPosition, wxSize(180, -1), 0); m_text_license->Wrap(-1); m_sizer_license->Add(m_text_license, 0, wxALIGN_CENTER, 0); - m_combo_license = new wxComboBox(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(450, -1), 0, NULL, wxCB_READONLY); + m_combo_license = new ComboBox(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(FromDIP(450), -1), 0, NULL, wxCB_READONLY); m_sizer_license->Add(m_combo_license, 0, wxALIGN_CENTER, 0); - */ + m_sizer_body->Add( 0, 0, 0, wxTOP, FromDIP(50) ); m_sizer_body->Add(m_sizer_designer, 0, wxLEFT, FromDIP(50)); m_sizer_body->Add( 0, 0, 0, wxTOP, FromDIP(20)); m_sizer_body->Add(m_sizer_model_name, 0, wxLEFT, FromDIP(50)); - //m_sizer_body->Add(0, 0, 0, wxTOP, FromDIP(20)); - //m_sizer_body->Add(m_sizer_license, 0, wxLEFT, FromDIP(50)); - //init_license_list(); + m_sizer_body->Add(0, 0, 0, wxTOP, FromDIP(20)); + m_sizer_body->Add(m_sizer_license, 0, wxLEFT, FromDIP(50)); + init_license_list(); SetSizer(m_sizer_body); Layout(); @@ -1144,52 +1103,35 @@ void AuxiliaryPanel::update_all_cover() m_input_designer->Bind(wxEVT_TEXT, &DesignerPanel::on_input_enter_designer, this); m_imput_model_name->Bind(wxEVT_TEXT, &DesignerPanel::on_input_enter_model, this); - //m_combo_license->Connect(wxEVT_COMMAND_COMBOBOX_SELECTED, wxCommandEventHandler(DesignerPanel::on_select_license), NULL, this); + m_combo_license->Bind(wxEVT_COMMAND_COMBOBOX_SELECTED, &DesignerPanel::on_select_license, this); } DesignerPanel::~DesignerPanel() { - //m_combo_license->Disconnect(wxEVT_COMMAND_COMBOBOX_SELECTED, wxCommandEventHandler(DesignerPanel::on_select_license), NULL, this); } void DesignerPanel::init_license_list() { - /* wxArrayString text_licese; for (int i = 0; i < license_list.size(); i++) { text_licese.Add(license_list[i]); } m_combo_license->Set(text_licese); - */ } void DesignerPanel::on_select_license(wxCommandEvent&evt) { int selected = evt.GetInt(); if (selected >= 0 && selected < license_list.size()) { - if (wxGetApp().plater()->model().model_info == nullptr) { - wxGetApp().plater()->model().model_info = std::make_shared(); - } - if (wxGetApp().plater()->model().model_info != nullptr) { - wxGetApp().plater()->model().model_info->license = license_list[selected]; - } + ensure_model_info()->license = license_list[selected]; } } -bool DesignerPanel::Show(bool show) -{ - if ( wxGetApp().plater()->model().design_info != nullptr) { - wxString text = wxString::FromUTF8(wxGetApp().plater()->model().design_info->Designer); - m_input_designer->GetTextCtrl()->SetValue(text); - } - - if (wxGetApp().plater()->model().model_info != nullptr) { - wxString text = wxString::FromUTF8(wxGetApp().plater()->model().model_info->model_name); - m_imput_model_name->GetTextCtrl()->SetValue(text); - } - - return wxPanel::Show(show); -} +bool DesignerPanel::Show(bool show) + { + if (show) update_info(); + return wxPanel::Show(show); + } void DesignerPanel::on_input_enter_designer(wxCommandEvent &evt) { @@ -1200,9 +1142,7 @@ void DesignerPanel::on_input_enter_designer(wxCommandEvent &evt) void DesignerPanel::on_input_enter_model(wxCommandEvent &evt) { auto text = evt.GetString(); - if (wxGetApp().plater()->model().model_info) { - wxGetApp().plater()->model().model_info->model_name = std::string(text.ToUTF8().data()); - } + ensure_model_info()->model_name = std::string(text.ToUTF8().data()); } void DesignerPanel::update_info() @@ -1215,10 +1155,13 @@ void DesignerPanel::update_info() } if (wxGetApp().plater()->model().model_info != nullptr) { - wxString text = wxString::FromUTF8(wxGetApp().plater()->model().model_info->model_name); - m_imput_model_name->GetTextCtrl()->SetValue(text); + m_imput_model_name->GetTextCtrl()->SetValue(wxString::FromUTF8(wxGetApp().plater()->model().model_info->model_name)); + if (!m_combo_license->SetStringSelection(wxString::FromUTF8(wxGetApp().plater()->model().model_info->license))) { + m_combo_license->SetSelection(0); + } } else { - m_imput_model_name->GetTextCtrl()->SetValue(wxEmptyString); + m_imput_model_name->GetTextCtrl()->SetValue(wxEmptyString); + m_combo_license->SetSelection(0); } } @@ -1226,6 +1169,7 @@ void DesignerPanel::msw_rescale() { m_input_designer->GetTextCtrl()->SetSize(wxSize(FromDIP(450), -1)); m_imput_model_name->GetTextCtrl()->SetSize(wxSize(FromDIP(450), -1)); + m_combo_license->SetSize(wxSize(FromDIP(450), -1)); } }} // namespace Slic3r::GUI diff --git a/src/slic3r/GUI/Auxiliary.hpp b/src/slic3r/GUI/Auxiliary.hpp index b8340167fc..b1378d0878 100644 --- a/src/slic3r/GUI/Auxiliary.hpp +++ b/src/slic3r/GUI/Auxiliary.hpp @@ -181,7 +181,7 @@ public: ::TextInput* m_input_designer {nullptr}; ::TextInput* m_imput_model_name {nullptr}; - //wxComboBox* m_combo_license {nullptr}; + ComboBox* m_combo_license {nullptr}; bool Show(bool show) override; void init_license_list(); void on_input_enter_designer(wxCommandEvent &evt); @@ -232,7 +232,7 @@ public: void create_folder(wxString name = wxEmptyString); std::string replaceSpace(std::string s, std::string ts, std::string ns); void on_import_file(wxCommandEvent &event); - void Reload(wxString aux_path); + void Reload(wxString aux_path, std::map> paths); void update_all_panel(); void update_all_cover(); @@ -242,6 +242,7 @@ wxDECLARE_EVENT(EVT_AUXILIARY_IMPORT, wxCommandEvent); wxDECLARE_EVENT(EVT_AUXILIARY_UPDATE_COVER, wxCommandEvent); wxDECLARE_EVENT(EVT_AUXILIARY_UPDATE_DELETE, wxCommandEvent); wxDECLARE_EVENT(EVT_AUXILIARY_UPDATE_RENAME, wxCommandEvent); +wxDECLARE_EVENT(EVT_AUXILIARY_DONE, wxCommandEvent); }} // namespace Slic3r::GUI #endif diff --git a/src/slic3r/GUI/ConfigManipulation.cpp b/src/slic3r/GUI/ConfigManipulation.cpp index f6bbcecf09..69d5279334 100644 --- a/src/slic3r/GUI/ConfigManipulation.cpp +++ b/src/slic3r/GUI/ConfigManipulation.cpp @@ -661,9 +661,10 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co for (auto el : { "ironing_pattern", "ironing_flow", "ironing_spacing", "ironing_speed", "ironing_angle" }) toggle_line(el, has_ironing); - // bool have_sequential_printing = (config->opt_enum("print_sequence") == PrintSequence::ByObject); + bool have_sequential_printing = (config->opt_enum("print_sequence") == PrintSequence::ByObject); // for (auto el : { "extruder_clearance_radius", "extruder_clearance_height_to_rod", "extruder_clearance_height_to_lid" }) // toggle_field(el, have_sequential_printing); + toggle_field("print_order", !have_sequential_printing); bool have_ooze_prevention = config->opt_bool("ooze_prevention"); toggle_field("standby_temperature_delta", have_ooze_prevention); @@ -742,6 +743,10 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co apply(config, &new_conf); } toggle_line("timelapse_type", is_BBL_Printer); + + + bool have_small_area_infill_flow_compensation = config->opt_bool("small_area_infill_flow_compensation"); + toggle_line("small_area_infill_flow_compensation_model", have_small_area_infill_flow_compensation); } void ConfigManipulation::update_print_sla_config(DynamicPrintConfig* config, const bool is_global_config/* = false*/) diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index fc50c716a1..05670cb472 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -7304,10 +7304,10 @@ void GLCanvas3D::_render_overlays() auto curr_plate = wxGetApp().plater()->get_partplate_list().get_curr_plate(); auto curr_print_seq = curr_plate->get_real_print_seq(); - bool sequential_print = (curr_print_seq == PrintSequence::ByObject); + const Print* print = fff_print(); + bool sequential_print = (curr_print_seq == PrintSequence::ByObject) || print->config().print_order == PrintOrder::AsObjectList; std::vector sorted_instances; if (sequential_print) { - const Print* print = fff_print(); if (print) { for (const PrintObject *print_object : print->objects()) { diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 567009fdb9..2273a91f2c 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -2656,7 +2656,7 @@ bool GUI_App::on_init_inner() sidebar().obj_list()->init(); //sidebar().aux_list()->init_auxiliary(); - //mainframe->m_auxiliary->init_auxiliary(); + mainframe->m_project->init_auxiliary(); // update_mode(); // !!! do that later SetTopWindow(mainframe); diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 40df07ba8d..c41285fc66 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -1545,26 +1545,6 @@ void ObjectList::OnBeginDrag(wxDataViewEvent &event) } if (type & itObject) { - int curr_obj_id = m_objects_model->GetIdByItem(event.GetItem()); - PartPlateList& partplate_list = wxGetApp().plater()->get_partplate_list(); - int from_plate = partplate_list.find_instance(curr_obj_id, 0); - if (from_plate == -1) { - event.Veto(); - return; - } - auto curr_plate_seq = partplate_list.get_plate(from_plate)->get_print_seq(); - if (curr_plate_seq == PrintSequence::ByDefault) { - auto curr_preset_config = wxGetApp().preset_bundle->prints.get_edited_preset().config; - if (curr_preset_config.has("print_sequence")) - curr_plate_seq = curr_preset_config.option>("print_sequence")->value; - } - - if (curr_plate_seq != PrintSequence::ByObject) { - //drag forbidden under bylayer mode - event.Veto(); - return; - } - m_dragged_data.init(m_objects_model->GetIdByItem(item), type); } else if (type & itVolume){ diff --git a/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp b/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp index a61b4a5b0a..62afc1c402 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp @@ -717,7 +717,12 @@ bool GLGizmoCut3D::render_reset_button(const std::string& label_id, const std::s static double get_grabber_mean_size(const BoundingBoxf3& bb) { +#if ENABLE_FIXED_GRABBER + // Orca: make grabber larger + return 32. * GLGizmoBase::INV_ZOOM; +#else return (bb.size().x() + bb.size().y() + bb.size().z()) / 30.; +#endif } indexed_triangle_set GLGizmoCut3D::its_make_groove_plane() @@ -2503,13 +2508,13 @@ void GLGizmoCut3D::add_horizontal_shift(float shift) void GLGizmoCut3D::render_color_marker(float size, const ImU32& color) { - ImGui::SameLine(); const float radius = 0.5f * size; ImVec2 pos = ImGui::GetCurrentWindow()->DC.CursorPos; - pos.x += size; - pos.y += 1.25f * radius; + pos.x += radius; + pos.y += 1.4f * radius; ImGui::GetCurrentWindow()->DrawList->AddNgonFilled(pos, radius, color, 6); - m_imgui->text(" "); + m_imgui->text(" "); + ImGui::SameLine(); } void GLGizmoCut3D::render_groove_float_input(const std::string& label, float& in_val, const float& init_val, float& in_tolerance) @@ -2730,20 +2735,27 @@ void GLGizmoCut3D::render_cut_plane_input_window(CutConnectors &connectors, floa // render "After Cut" section - float label_width = 0; + ImVec2 label_size; for (const wxString &label : {_L("Upper part"), _L("Lower part")}) { - const float width = m_imgui->calc_text_size(label).x + m_imgui->scaled(1.5f); - if (label_width < width) - label_width = width; + const ImVec2 text_size = ImGuiWrapper::calc_text_size(label); + if (label_size.x < text_size.x) + label_size.x = text_size.x; + if (label_size.y < text_size.y) + label_size.y = text_size.y; } - auto render_part_action_line = [this, label_width, &connectors](const wxString &label, const wxString &suffix, bool &keep_part, + const float marker_size = label_size.y; + const float h_shift = marker_size + label_size.x + m_imgui->scaled(2.f); + + auto render_part_action_line = [this, h_shift, marker_size, &connectors](const wxString &label, const wxString &suffix, bool &keep_part, bool &place_on_cut_part, bool &rotate_part) { bool keep = true; + ImGui::AlignTextToFramePadding(); + render_color_marker(marker_size, ImGuiWrapper::to_ImU32(suffix == "##upper" ? UPPER_PART_COLOR : LOWER_PART_COLOR)); m_imgui->text(label); - ImGui::SameLine(label_width); + ImGui::SameLine(h_shift); m_imgui->disabled_begin(!connectors.empty() || m_keep_as_parts); m_imgui->bbl_checkbox(_L("Keep") + suffix, connectors.empty() ? keep_part : keep); diff --git a/src/slic3r/GUI/PartPlate.cpp b/src/slic3r/GUI/PartPlate.cpp index b2e393f528..6b0d8c6406 100644 --- a/src/slic3r/GUI/PartPlate.cpp +++ b/src/slic3r/GUI/PartPlate.cpp @@ -51,6 +51,7 @@ static unsigned int GLOBAL_PLATE_INDEX = 0; static const double LOGICAL_PART_PLATE_GAP = 1. / 5.; static const int PARTPLATE_ICON_SIZE = 16; +static const int PARTPLATE_EDIT_PLATE_NAME_ICON_SIZE = 12; static const int PARTPLATE_ICON_GAP_TOP = 3; static const int PARTPLATE_ICON_GAP_LEFT = 3; static const int PARTPLATE_ICON_GAP_Y = 5; @@ -571,6 +572,42 @@ void PartPlate::calc_vertex_for_number(int index, bool one_number, GLModel &buff BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << "Unable to generate geometry buffers for icons\n"; } +void PartPlate::calc_vertex_for_plate_name_edit_icon(GLTexture *texture, int index, PickingModel &model) { + model.reset(); + + auto bed_ext = get_extents(m_shape); + auto factor = bed_ext.size()(1) / 200.0; + wxCoord w, h; + h = int(factor * 16); + ExPolygon poly; + Vec2d p = bed_ext[3]; + float offset_x = 1; + h = PARTPLATE_EDIT_PLATE_NAME_ICON_SIZE; + p += Vec2d(0, PARTPLATE_TEXT_OFFSET_Y + h); + if (texture && texture->get_width() > 0 && texture->get_height()) { + w = int(factor * (texture->get_original_width() * 16) / texture->get_height()) + 1; + + poly.contour.append({scale_(p(0) + PARTPLATE_ICON_GAP_LEFT + w), scale_(p(1) - h )}); + poly.contour.append({scale_(p(0) + PARTPLATE_ICON_GAP_LEFT + w + PARTPLATE_EDIT_PLATE_NAME_ICON_SIZE), scale_(p(1) - h)}); + poly.contour.append({scale_(p(0) + PARTPLATE_ICON_GAP_LEFT + w + PARTPLATE_EDIT_PLATE_NAME_ICON_SIZE), scale_(p(1))}); + poly.contour.append({scale_(p(0) + PARTPLATE_ICON_GAP_LEFT + w), scale_(p(1) )}); + + if (!init_model_from_poly(model.model, poly, GROUND_Z)) + BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << "Unable to generate geometry buffers for icons\n"; + } else { + + poly.contour.append({scale_(p(0) + PARTPLATE_ICON_GAP_LEFT + offset_x ), scale_(p(1) - h )}); + poly.contour.append({scale_(p(0) + PARTPLATE_ICON_GAP_LEFT + offset_x + PARTPLATE_EDIT_PLATE_NAME_ICON_SIZE), scale_(p(1) - h)}); + poly.contour.append({scale_(p(0) + PARTPLATE_ICON_GAP_LEFT + offset_x + PARTPLATE_EDIT_PLATE_NAME_ICON_SIZE), scale_(p(1))}); + poly.contour.append({scale_(p(0) + PARTPLATE_ICON_GAP_LEFT + offset_x), scale_(p(1) )}); + + if (!init_model_from_poly(model.model, poly, GROUND_Z)) + BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << "Unable to generate geometry buffers for icons\n"; + } + + init_raycaster_from_model(model); +} + void PartPlate::calc_vertex_for_icons(int index, PickingModel &model) { model.reset(); @@ -975,6 +1012,13 @@ void PartPlate::render_icons(bool bottom, bool only_name, int hover_id) render_icon_texture(m_lock_icon.model, m_partplate_list->m_lockopen_texture); } + if (hover_id == 6) { + render_icon_texture(m_plate_name_edit_icon.model, m_partplate_list->m_plate_name_edit_hovered_texture); + show_tooltip(_u8L("Edit current plate name")); + } + else + render_icon_texture(m_plate_name_edit_icon.model, m_partplate_list->m_plate_name_edit_texture); + if (m_partplate_list->render_plate_settings) { if (hover_id == 5) { if (get_bed_type() == BedType::btDefault && get_print_seq() == PrintSequence::ByDefault && get_first_layer_print_sequence().empty()) @@ -1272,6 +1316,9 @@ void PartPlate::register_raycasters_for_picking(GLCanvas3D &canvas) register_model_for_picking(canvas, m_lock_icon, picking_id_component(4)); if (m_partplate_list->render_plate_settings) register_model_for_picking(canvas, m_plate_settings_icon, picking_id_component(5)); + + canvas.remove_raycasters_for_picking(SceneRaycaster::EType::Bed, picking_id_component(6)); + register_model_for_picking(canvas, m_plate_name_edit_icon, picking_id_component(6)); } int PartPlate::picking_id_component(int idx) const @@ -1781,7 +1828,12 @@ void PartPlate::generate_plate_name_texture() poly.contour.append({ scale_(p(0) + PARTPLATE_ICON_GAP_LEFT + offset_x), scale_(p(1) - PARTPLATE_TEXT_OFFSET_Y) }); if (!init_model_from_poly(m_plate_name_icon, poly, GROUND_Z)) - BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << "Unable to generate geometry buffers for icons\n"; + BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << "Unable to generate geometry buffers for icons\n"; + + auto canvas = this->m_partplate_list->m_plater->get_view3D_canvas3D(); + canvas->remove_raycasters_for_picking(SceneRaycaster::EType::Bed, picking_id_component(6)); + calc_vertex_for_plate_name_edit_icon(&m_name_texture, 0, m_plate_name_edit_icon); + register_model_for_picking(*canvas, m_plate_name_edit_icon, picking_id_component(6)); } void PartPlate::set_plate_name(const std::string& name) { @@ -3124,6 +3176,20 @@ void PartPlateList::generate_icon_textures() } } + // if (m_plate_name_edit_texture.get_id() == 0) + { + file_name = path + (m_is_dark ? "plate_name_edit_dark.svg" : "plate_name_edit.svg"); + if (!m_plate_name_edit_texture.load_from_svg_file(file_name, true, false, false, icon_size)) { + BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(":load file %1% failed") % file_name; + } + } + // if (m_plate_name_edit_hovered_texture.get_id() == 0) + { + file_name = path + (m_is_dark ? "plate_name_edit_hover_dark.svg" : "plate_name_edit_hover.svg"); + if (!m_plate_name_edit_hovered_texture.load_from_svg_file(file_name, true, false, false, icon_size)) { + BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(":load file %1% failed") % file_name; + } + } std::string text_str = "01"; wxFont* font = find_font(text_str,32); @@ -3161,7 +3227,8 @@ void PartPlateList::release_icon_textures() m_plate_settings_texture.reset(); m_plate_settings_texture.reset(); m_plate_settings_hovered_texture.reset(); - + m_plate_name_edit_texture.reset(); + m_plate_name_edit_hovered_texture.reset(); for (int i = 0;i < MAX_PLATE_COUNT; i++) { m_idx_textures[i].reset(); } diff --git a/src/slic3r/GUI/PartPlate.hpp b/src/slic3r/GUI/PartPlate.hpp index 4bf62680fe..b6c5d430ff 100644 --- a/src/slic3r/GUI/PartPlate.hpp +++ b/src/slic3r/GUI/PartPlate.hpp @@ -138,6 +138,7 @@ private: PickingModel m_orient_icon; PickingModel m_lock_icon; PickingModel m_plate_settings_icon; + PickingModel m_plate_name_edit_icon; GLModel m_plate_idx_icon; GLTexture m_texture; @@ -169,6 +170,7 @@ private: void calc_gridlines(const ExPolygon& poly, const BoundingBox& pp_bbox); void calc_height_limit(); void calc_vertex_for_number(int index, bool one_number, GLModel &buffer); + void calc_vertex_for_plate_name_edit_icon(GLTexture *texture, int index, PickingModel &model); void calc_vertex_for_icons(int index, PickingModel &model); // void calc_vertex_for_icons_background(int icon_count, GLModel &buffer); void render_background(bool force_default_color = false); diff --git a/src/slic3r/GUI/Project.cpp b/src/slic3r/GUI/Project.cpp index aefffccc09..46e3c34429 100644 --- a/src/slic3r/GUI/Project.cpp +++ b/src/slic3r/GUI/Project.cpp @@ -62,6 +62,11 @@ ProjectPanel::ProjectPanel(wxWindow *parent, wxWindowID id, const wxPoint &pos, Bind(EVT_PROJECT_RELOAD, &ProjectPanel::on_reload, this); + m_auxiliary = new AuxiliaryPanel(this); + m_auxiliary->Hide(); + main_sizer->Add(m_auxiliary, wxSizerFlags().Expand().Proportion(1)); + Bind(EVT_AUXILIARY_DONE, [this](wxCommandEvent& e) { update_model_data();}); + SetSizer(main_sizer); Layout(); Fit(); @@ -91,38 +96,39 @@ void ProjectPanel::on_reload(wxCommandEvent& evt) std::string model_author; std::string cover_file; std::string description; - std::map> files; - std::string p_name; std::string p_author; std::string p_description; std::string p_cover_file; + std::map> files; + Model model = wxGetApp().plater()->model(); - license = model.model_info->license; - model_name = model.model_info->model_name; - cover_file = model.model_info->cover_file; - description = model.model_info->description; - update_type = model.model_info->origin; + auto model_info = model.model_info; + if (model_info != nullptr) { + license = model_info->license; + model_name = model_info->model_name; + cover_file = model_info->cover_file; + description = model_info->description; + update_type = model_info->origin; + try { + if (!model_info->copyright.empty()) { + json copy_right = json::parse(model_info->copyright); - try { - if (!model.model_info->copyright.empty()) { - json copy_right = json::parse(model.model_info->copyright); - - if (copy_right.is_array()) { - for (auto it = copy_right.begin(); it != copy_right.end(); it++) { - if ((*it).contains("author")) { - model_author = (*it)["author"].get(); + if (copy_right.is_array()) { + for (auto it = copy_right.begin(); it != copy_right.end(); it++) { + if ((*it).contains("author")) { + model_author = (*it)["author"].get(); + } } } } + } catch (...) { + ; } } - catch (...) { - ; - } if (model_author.empty() && model.design_info != nullptr) model_author = model.design_info->Designer; @@ -134,12 +140,44 @@ void ProjectPanel::on_reload(wxCommandEvent& evt) p_author = model.profile_info->ProfileUserName; } - //file info + // file info std::string file_path = encode_path(wxGetApp().plater()->model().get_auxiliary_file_temp_path().c_str()); if (!file_path.empty()) { files = Reload(file_path); + wxGetApp().CallAfter([this, file_path, files] { m_auxiliary->Reload(file_path, files); }); + } else { + clear_model_info(); + return; } - else { + + bool has_content = false; + for (const string& v : { + update_type, + license, + model_name, + model_author, + cover_file, + description, + p_name, + p_author, + p_description, + p_cover_file, + }) { + if (!v.empty()) { + has_content = true; + break; + } + } + if (!has_content) { + for (const auto & file : files) { + if (!file.second.empty()) { + has_content = true; + break; + } + } + } + if (!has_content) { + // Nothing to show, just return clear_model_info(); return; } @@ -180,6 +218,7 @@ void ProjectPanel::on_reload(wxCommandEvent& evt) void ProjectPanel::msw_rescale() { + m_auxiliary->msw_rescale(); } void ProjectPanel::on_size(wxSizeEvent &event) @@ -215,6 +254,9 @@ void ProjectPanel::OnScriptMessage(wxWebViewEvent& evt) else if (strCmd == "request_3mf_info") { m_web_init_completed = true; } + else if (strCmd == "edit_project_info") { + show_info_editor(true); + } else if (strCmd == "debug_info") { //wxString msg = j["msg"]; //OutputDebugString(wxString::Format("Model_Web: msg = %s \r\n", msg)); @@ -227,14 +269,24 @@ void ProjectPanel::OnScriptMessage(wxWebViewEvent& evt) } } +void ProjectPanel::show_info_editor(bool show) +{ + m_browser->Show(!show); + m_auxiliary->Show(show); + Layout(); +} + void ProjectPanel::update_model_data() { Model model = wxGetApp().plater()->model(); + show_info_editor(false); clear_model_info(); + m_auxiliary->init_auxiliary(); + //basics info - if (model.model_info == nullptr) - return; + //if (model.model_info == nullptr) + // return; auto event = wxCommandEvent(EVT_PROJECT_RELOAD); event.SetEventObject(this); @@ -258,7 +310,6 @@ std::map> ProjectPanel::Reload(wxString aux_path) { std::vector dir_cache; fs::directory_iterator iter_end; - wxString m_root_dir; std::map> m_paths_list; const static std::array s_default_folders = { @@ -276,24 +327,16 @@ std::map> ProjectPanel::Reload(wxString aux_path) fs::path new_aux_path(aux_path.ToStdWstring()); - try { - fs::remove_all(fs::path(m_root_dir.ToStdWstring())); - } - catch (...) { - BOOST_LOG_TRIVIAL(error) << "Failed removing the auxiliary directory" << m_root_dir.c_str(); - } - - m_root_dir = aux_path; // Check new path. If not exist, create a new one. if (!fs::exists(new_aux_path)) { fs::create_directory(new_aux_path); - // Create default folders if they are not loaded - for (auto folder : s_default_folders) { - wxString folder_path = aux_path + "/" + folder; - if (fs::exists(folder_path.ToStdWstring())) continue; - fs::create_directory(folder_path.ToStdWstring()); - } - return m_paths_list; + } + + // Create default folders if they are not loaded + for (auto folder : s_default_folders) { + wxString folder_path = aux_path + "/" + folder; + if (fs::exists(folder_path.ToStdWstring())) continue; + fs::create_directory(folder_path.ToStdWstring()); } // Load from new path @@ -320,7 +363,8 @@ std::map> ProjectPanel::Reload(wxString aux_path) wxString file_name = encode_path(file_path.c_str()); wxStat(file_name, &strucStat); wxFileOffset filelen = strucStat.st_size; - + + pfile_obj["_filepath"] = file_path; pfile_obj["filename"] = wxGetApp().url_encode(file_path_obj.filename().string().c_str()); pfile_obj["size"] = formatBytes((unsigned long)filelen); diff --git a/src/slic3r/GUI/Project.hpp b/src/slic3r/GUI/Project.hpp index 70aa3348e0..99b081527a 100644 --- a/src/slic3r/GUI/Project.hpp +++ b/src/slic3r/GUI/Project.hpp @@ -32,6 +32,7 @@ #include "Event.hpp" #include "libslic3r/ProjectTask.hpp" #include "wxExtensions.hpp" +#include "Auxiliary.hpp" #define AUFILE_GREY700 wxColour(107, 107, 107) #define AUFILE_GREY500 wxColour(158, 158, 158) @@ -63,9 +64,12 @@ private: bool m_reload_already = {false}; wxWebView* m_browser = {nullptr}; + AuxiliaryPanel* m_auxiliary{nullptr}; wxString m_project_home_url; wxString m_root_dir; static inline int m_sequence_id = 8000; + + void show_info_editor(bool show); public: @@ -81,6 +85,7 @@ public: void msw_rescale(); void update_model_data(); void clear_model_info(); + void init_auxiliary() { m_auxiliary->init_auxiliary(); } bool Show(bool show); void OnScriptMessage(wxWebViewEvent& evt); diff --git a/src/slic3r/GUI/Selection.cpp b/src/slic3r/GUI/Selection.cpp index 7b605a58d9..41e7bc9316 100644 --- a/src/slic3r/GUI/Selection.cpp +++ b/src/slic3r/GUI/Selection.cpp @@ -1324,8 +1324,11 @@ void Selection::scale_legacy(const Vec3d& scale, TransformationType transformati v.set_instance_offset(m_cache.dragging_center + m * (m_cache.volumes_data[i].get_instance_position() - m_cache.dragging_center)); v.set_instance_scaling_factor(new_scale); + // Restore mirror state + v.set_instance_mirror(m_cache.volumes_data[i].get_instance_transform().get_mirror()); } else { + const auto mirror = v.get_instance_mirror(); if (transformation_type.world() && (std::abs(scale.x() - scale.y()) > EPSILON || std::abs(scale.x() - scale.z()) > EPSILON)) { // Non-uniform scaling. Transform the scaling factors into the local coordinate system. // This is only possible, if the instance rotation is mulitples of ninety degrees. @@ -1334,16 +1337,24 @@ void Selection::scale_legacy(const Vec3d& scale, TransformationType transformati } else v.set_instance_scaling_factor(scale); + // Restore mirror state + v.set_instance_mirror(mirror); } // update the instance assemble transform ModelObject* object = m_model->objects[v.object_idx()]; Geometry::Transformation assemble_transform = object->instances[v.instance_idx()]->get_assemble_transformation(); + const auto mirror = assemble_transform.get_mirror(); assemble_transform.set_scaling_factor(v.get_instance_scaling_factor()); + assemble_transform.set_mirror(mirror); object->instances[v.instance_idx()]->set_assemble_transformation(assemble_transform); } - else if (is_single_volume() || is_single_modifier()) + else if (is_single_volume() || is_single_modifier()) { + const auto mirror = v.get_volume_transformation().get_mirror(); v.set_volume_scaling_factor(scale); + // Restore mirror state + v.set_volume_mirror(mirror); + } else { Transform3d m = Geometry::assemble_transform(Vec3d::Zero(), Vec3d::Zero(), scale); if (m_mode == Instance) { @@ -1354,6 +1365,8 @@ void Selection::scale_legacy(const Vec3d& scale, TransformationType transformati v.set_instance_offset(m_cache.dragging_center + m * (m_cache.volumes_data[i].get_instance_position() - m_cache.dragging_center)); v.set_instance_scaling_factor(new_scale); + // Restore mirror state + v.set_instance_mirror(m_cache.volumes_data[i].get_instance_transform().get_mirror()); } else if (m_mode == Volume) { Eigen::Matrix new_matrix = (m * m_cache.volumes_data[i].get_volume_scale_matrix()).matrix().block(0, 0, 3, 3); @@ -1364,6 +1377,8 @@ void Selection::scale_legacy(const Vec3d& scale, TransformationType transformati v.set_volume_offset(m_cache.dragging_center - m_cache.volumes_data[i].get_instance_position() + offset); } v.set_volume_scaling_factor(new_scale); + // Restore mirror state + v.set_volume_mirror(m_cache.volumes_data[i].get_volume_transform().get_mirror()); } } } diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 325a56d8c6..9f7f2d65e2 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -1988,6 +1988,14 @@ void TabPrint::build() optgroup->append_single_option_line("only_one_wall_first_layer"); optgroup->append_single_option_line("reduce_crossing_wall"); optgroup->append_single_option_line("max_travel_detour_distance"); + + optgroup = page->new_optgroup(L("Small Area Infill Flow Compensation (experimental)"), L"param_advanced"); + optgroup->append_single_option_line("small_area_infill_flow_compensation"); + Option option = optgroup->get_option("small_area_infill_flow_compensation_model"); + option.opt.full_width = true; + option.opt.is_code = true; + option.opt.height = 15; + optgroup->append_single_option_line(option); optgroup = page->new_optgroup(L("Bridging"), L"param_advanced"); optgroup->append_single_option_line("bridge_flow"); @@ -2198,6 +2206,7 @@ void TabPrint::build() optgroup = page->new_optgroup(L("Special mode"), L"param_special"); optgroup->append_single_option_line("slicing_mode"); optgroup->append_single_option_line("print_sequence", "sequent-print"); + optgroup->append_single_option_line("print_order"); optgroup->append_single_option_line("spiral_mode", "spiral-vase"); optgroup->append_single_option_line("spiral_mode_smooth", "spiral-vase#smooth"); optgroup->append_single_option_line("spiral_mode_max_xy_smoothing", "spiral-vase#max-xy-smoothing"); @@ -2218,7 +2227,7 @@ void TabPrint::build() optgroup->append_single_option_line("gcode_comments"); optgroup->append_single_option_line("gcode_label_objects"); optgroup->append_single_option_line("exclude_object"); - Option option = optgroup->get_option("filename_format"); + option = optgroup->get_option("filename_format"); // option.opt.full_width = true; option.opt.is_code = true; option.opt.multiline = true; diff --git a/src/spline/spline.h b/src/spline/spline.h new file mode 100644 index 0000000000..c8f08418fb --- /dev/null +++ b/src/spline/spline.h @@ -0,0 +1,951 @@ +/* + * spline.h + * + * simple cubic spline interpolation library without external + * dependencies + * + * --------------------------------------------------------------------- + * Copyright (C) 2011, 2014, 2016, 2021 Tino Kluge (ttk448 at gmail.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * --------------------------------------------------------------------- + * + */ + + +#ifndef TK_SPLINE_H +#define TK_SPLINE_H + +#include +#include +#include +#include +#include +#ifdef HAVE_SSTREAM +#include +#include +#endif // HAVE_SSTREAM + +// not ideal but disable unused-function warnings +// (we get them because we have implementations in the header file, +// and this is because we want to be able to quickly separate them +// into a cpp file if necessary) +#if !defined(_MSC_VER) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-function" +#endif + +// unnamed namespace only because the implementation is in this +// header file and we don't want to export symbols to the obj files +namespace +{ + +namespace tk +{ + +// spline interpolation +class spline +{ +public: + // spline types + enum spline_type { + linear = 10, // linear interpolation + cspline = 30, // cubic splines (classical C^2) + cspline_hermite = 31 // cubic hermite splines (local, only C^1) + }; + + // boundary condition type for the spline end-points + enum bd_type { + first_deriv = 1, + second_deriv = 2, + not_a_knot = 3 + }; + +protected: + std::vector m_x,m_y; // x,y coordinates of points + // interpolation parameters + // f(x) = a_i + b_i*(x-x_i) + c_i*(x-x_i)^2 + d_i*(x-x_i)^3 + // where a_i = y_i, or else it won't go through grid points + std::vector m_b,m_c,m_d; // spline coefficients + double m_c0; // for left extrapolation + spline_type m_type; + bd_type m_left, m_right; + double m_left_value, m_right_value; + bool m_made_monotonic; + void set_coeffs_from_b(); // calculate c_i, d_i from b_i + size_t find_closest(double x) const; // closest idx so that m_x[idx]<=x + +public: + // default constructor: set boundary condition to be zero curvature + // at both ends, i.e. natural splines + spline(): m_type(cspline), + m_left(second_deriv), m_right(second_deriv), + m_left_value(0.0), m_right_value(0.0), m_made_monotonic(false) + { + ; + } + spline(const std::vector& X, const std::vector& Y, + spline_type type = cspline, + bool make_monotonic = false, + bd_type left = second_deriv, double left_value = 0.0, + bd_type right = second_deriv, double right_value = 0.0 + ): + m_type(type), + m_left(left), m_right(right), + m_left_value(left_value), m_right_value(right_value), + m_made_monotonic(false) // false correct here: make_monotonic() sets it + { + this->set_points(X,Y,m_type); + if(make_monotonic) { + this->make_monotonic(); + } + } + + + // modify boundary conditions: if called it must be before set_points() + void set_boundary(bd_type left, double left_value, + bd_type right, double right_value); + + // set all data points (cubic_spline=false means linear interpolation) + void set_points(const std::vector& x, + const std::vector& y, + spline_type type=cspline); + + // adjust coefficients so that the spline becomes piecewise monotonic + // where possible + // this is done by adjusting slopes at grid points by a non-negative + // factor and this will break C^2 + // this can also break boundary conditions if adjustments need to + // be made at the boundary points + // returns false if no adjustments have been made, true otherwise + bool make_monotonic(); + + // evaluates the spline at point x + double operator() (double x) const; + double deriv(int order, double x) const; + + // solves for all x so that: spline(x) = y + std::vector solve(double y, bool ignore_extrapolation=true) const; + + // returns the input data points + std::vector get_x() const { return m_x; } + std::vector get_y() const { return m_y; } + double get_x_min() const { assert(!m_x.empty()); return m_x.front(); } + double get_x_max() const { assert(!m_x.empty()); return m_x.back(); } + +#ifdef HAVE_SSTREAM + // spline info string, i.e. spline type, boundary conditions etc. + std::string info() const; +#endif // HAVE_SSTREAM + +}; + + + +namespace internal +{ + +// band matrix solver +class band_matrix +{ +private: + std::vector< std::vector > m_upper; // upper band + std::vector< std::vector > m_lower; // lower band +public: + band_matrix() {}; // constructor + band_matrix(int dim, int n_u, int n_l); // constructor + ~band_matrix() {}; // destructor + void resize(int dim, int n_u, int n_l); // init with dim,n_u,n_l + int dim() const; // matrix dimension + int num_upper() const + { + return (int)m_upper.size()-1; + } + int num_lower() const + { + return (int)m_lower.size()-1; + } + // access operator + double & operator () (int i, int j); // write + double operator () (int i, int j) const; // read + // we can store an additional diagonal (in m_lower) + double& saved_diag(int i); + double saved_diag(int i) const; + void lu_decompose(); + std::vector r_solve(const std::vector& b) const; + std::vector l_solve(const std::vector& b) const; + std::vector lu_solve(const std::vector& b, + bool is_lu_decomposed=false); + +}; + +double get_eps(); + +std::vector solve_cubic(double a, double b, double c, double d, + int newton_iter=0); + +} // namespace internal + + + + +// --------------------------------------------------------------------- +// implementation part, which could be separated into a cpp file +// --------------------------------------------------------------------- + +// spline implementation +// ----------------------- + +void spline::set_boundary(spline::bd_type left, double left_value, + spline::bd_type right, double right_value) +{ + assert(m_x.size()==0); // set_points() must not have happened yet + m_left=left; + m_right=right; + m_left_value=left_value; + m_right_value=right_value; +} + + +void spline::set_coeffs_from_b() +{ + assert(m_x.size()==m_y.size()); + assert(m_x.size()==m_b.size()); + assert(m_x.size()>2); + size_t n=m_b.size(); + if(m_c.size()!=n) + m_c.resize(n); + if(m_d.size()!=n) + m_d.resize(n); + + for(size_t i=0; i& x, + const std::vector& y, + spline_type type) +{ + assert(x.size()==y.size()); + assert(x.size()>=3); + // not-a-knot with 3 points has many solutions + if(m_left==not_a_knot || m_right==not_a_knot) + assert(x.size()>=4); + m_type=type; + m_made_monotonic=false; + m_x=x; + m_y=y; + int n = (int) x.size(); + // check strict monotonicity of input vector x + for(int i=0; i rhs(n); + for(int i=1; i2); + bool modified = false; + const int n=(int)m_x.size(); + // make sure: input data monotonic increasing --> b_i>=0 + // input data monotonic decreasing --> b_i<=0 + for(int i=0; i=m_y[i]) && (m_y[i]>=m_y[ip1]) && m_b[i]>0.0) ) { + modified=true; + m_b[i]=0.0; + } + } + // if input data is monotonic (b[i], b[i+1], avg have all the same sign) + // ensure a sufficient criteria for monotonicity is satisfied: + // sqrt(b[i]^2+b[i+1]^2) <= 3 |avg|, with avg=(y[i+1]-y[i])/h, + for(int i=0; i=0.0 && m_b[i+1]>=0.0 && avg>0.0) || + (m_b[i]<=0.0 && m_b[i+1]<=0.0 && avg<0.0) ) { + // input data is monotonic + double r = sqrt(m_b[i]*m_b[i]+m_b[i+1]*m_b[i+1])/std::fabs(avg); + if(r>3.0) { + // sufficient criteria for monotonicity: r<=3 + // adjust b[i] and b[i+1] + modified=true; + m_b[i] *= (3.0/r); + m_b[i+1] *= (3.0/r); + } + } + } + + if(modified==true) { + set_coeffs_from_b(); + m_made_monotonic=true; + } + + return modified; +} + +// return the closest idx so that m_x[idx] <= x (return 0 if x::const_iterator it; + it=std::upper_bound(m_x.begin(),m_x.end(),x); // *it > x + size_t idx = std::max( int(it-m_x.begin())-1, 0); // m_x[idx] <= x + return idx; +} + +double spline::operator() (double x) const +{ + // polynomial evaluation using Horner's scheme + // TODO: consider more numerically accurate algorithms, e.g.: + // - Clenshaw + // - Even-Odd method by A.C.R. Newbery + // - Compensated Horner Scheme + size_t n=m_x.size(); + size_t idx=find_closest(x); + + double h=x-m_x[idx]; + double interpol; + if(xm_x[n-1]) { + // extrapolation to the right + interpol=(m_c[n-1]*h + m_b[n-1])*h + m_y[n-1]; + } else { + // interpolation + interpol=((m_d[idx]*h + m_c[idx])*h + m_b[idx])*h + m_y[idx]; + } + return interpol; +} + +double spline::deriv(int order, double x) const +{ + assert(order>0); + size_t n=m_x.size(); + size_t idx = find_closest(x); + + double h=x-m_x[idx]; + double interpol; + if(xm_x[n-1]) { + // extrapolation to the right + switch(order) { + case 1: + interpol=2.0*m_c[n-1]*h + m_b[n-1]; + break; + case 2: + interpol=2.0*m_c[n-1]; + break; + default: + interpol=0.0; + break; + } + } else { + // interpolation + switch(order) { + case 1: + interpol=(3.0*m_d[idx]*h + 2.0*m_c[idx])*h + m_b[idx]; + break; + case 2: + interpol=6.0*m_d[idx]*h + 2.0*m_c[idx]; + break; + case 3: + interpol=6.0*m_d[idx]; + break; + default: + interpol=0.0; + break; + } + } + return interpol; +} + +std::vector spline::solve(double y, bool ignore_extrapolation) const +{ + std::vector x; // roots for the entire spline + std::vector root; // roots for each piecewise cubic + const size_t n=m_x.size(); + + // left extrapolation + if(ignore_extrapolation==false) { + root = internal::solve_cubic(m_y[0]-y,m_b[0],m_c0,0.0,1); + for(size_t j=0; j0) ? (m_x[i]-m_x[i-1]) : 0.0; + double eps = internal::get_eps()*512.0*std::min(h,1.0); + if( (-eps<=root[j]) && (root[j]0 && x.back()+eps > new_root) { + x.back()=new_root; // avoid spurious duplicate roots + } else { + x.push_back(new_root); + } + } + } + } + + // right extrapolation + if(ignore_extrapolation==false) { + root = internal::solve_cubic(m_y[n-1]-y,m_b[n-1],m_c[n-1],0.0,1); + for(size_t j=0; j0); + assert(n_u>=0); + assert(n_l>=0); + m_upper.resize(n_u+1); + m_lower.resize(n_l+1); + for(size_t i=0; i0) { + return (int)m_upper[0].size(); + } else { + return 0; + } +} + + +// defines the new operator (), so that we can access the elements +// by A(i,j), index going from i=0,...,dim()-1 +double & band_matrix::operator () (int i, int j) +{ + int k=j-i; // what band is the entry + assert( (i>=0) && (i=0) && (j diagonal, k<0 lower left part, k>0 upper right part + if(k>=0) return m_upper[k][i]; + else return m_lower[-k][i]; +} +double band_matrix::operator () (int i, int j) const +{ + int k=j-i; // what band is the entry + assert( (i>=0) && (i=0) && (j diagonal, k<0 lower left part, k>0 upper right part + if(k>=0) return m_upper[k][i]; + else return m_lower[-k][i]; +} +// second diag (used in LU decomposition), saved in m_lower +double band_matrix::saved_diag(int i) const +{ + assert( (i>=0) && (i=0) && (idim(); i++) { + assert(this->operator()(i,i)!=0.0); + this->saved_diag(i)=1.0/this->operator()(i,i); + j_min=std::max(0,i-this->num_lower()); + j_max=std::min(this->dim()-1,i+this->num_upper()); + for(int j=j_min; j<=j_max; j++) { + this->operator()(i,j) *= this->saved_diag(i); + } + this->operator()(i,i)=1.0; // prevents rounding errors + } + + // Gauss LR-Decomposition + for(int k=0; kdim(); k++) { + i_max=std::min(this->dim()-1,k+this->num_lower()); // num_lower not a mistake! + for(int i=k+1; i<=i_max; i++) { + assert(this->operator()(k,k)!=0.0); + x=-this->operator()(i,k)/this->operator()(k,k); + this->operator()(i,k)=-x; // assembly part of L + j_max=std::min(this->dim()-1,k+this->num_upper()); + for(int j=k+1; j<=j_max; j++) { + // assembly part of R + this->operator()(i,j)=this->operator()(i,j)+x*this->operator()(k,j); + } + } + } +} +// solves Ly=b +std::vector band_matrix::l_solve(const std::vector& b) const +{ + assert( this->dim()==(int)b.size() ); + std::vector x(this->dim()); + int j_start; + double sum; + for(int i=0; idim(); i++) { + sum=0; + j_start=std::max(0,i-this->num_lower()); + for(int j=j_start; joperator()(i,j)*x[j]; + x[i]=(b[i]*this->saved_diag(i)) - sum; + } + return x; +} +// solves Rx=y +std::vector band_matrix::r_solve(const std::vector& b) const +{ + assert( this->dim()==(int)b.size() ); + std::vector x(this->dim()); + int j_stop; + double sum; + for(int i=this->dim()-1; i>=0; i--) { + sum=0; + j_stop=std::min(this->dim()-1,i+this->num_upper()); + for(int j=i+1; j<=j_stop; j++) sum += this->operator()(i,j)*x[j]; + x[i]=( b[i] - sum ) / this->operator()(i,i); + } + return x; +} + +std::vector band_matrix::lu_solve(const std::vector& b, + bool is_lu_decomposed) +{ + assert( this->dim()==(int)b.size() ); + std::vector x,y; + if(is_lu_decomposed==false) { + this->lu_decompose(); + } + y=this->l_solve(b); + x=this->r_solve(y); + return x; +} + +// machine precision of a double, i.e. the successor of 1 is 1+eps +double get_eps() +{ + //return std::numeric_limits::epsilon(); // __DBL_EPSILON__ + return 2.2204460492503131e-16; // 2^-52 +} + +// solutions for a + b*x = 0 +std::vector solve_linear(double a, double b) +{ + std::vector x; // roots + if(b==0.0) { + if(a==0.0) { + // 0*x = 0 + x.resize(1); + x[0] = 0.0; // any x solves it but we need to pick one + return x; + } else { + // 0*x + ... = 0, no solution + return x; + } + } else { + x.resize(1); + x[0] = -a/b; + return x; + } +} + +// solutions for a + b*x + c*x^2 = 0 +std::vector solve_quadratic(double a, double b, double c, + int newton_iter=0) +{ + if(c==0.0) { + return solve_linear(a,b); + } + // rescale so that we solve x^2 + 2p x + q = (x+p)^2 + q - p^2 = 0 + double p=0.5*b/c; + double q=a/c; + double discr = p*p-q; + const double eps=0.5*internal::get_eps(); + double discr_err = (6.0*(p*p)+3.0*fabs(q)+fabs(discr))*eps; + + std::vector x; // roots + if(fabs(discr)<=discr_err) { + // discriminant is zero --> one root + x.resize(1); + x[0] = -p; + } else if(discr<0) { + // no root + } else { + // two roots + x.resize(2); + x[0] = -p - sqrt(discr); + x[1] = -p + sqrt(discr); + } + + // improve solution via newton steps + for(size_t i=0; i1e-8) { + x[i] -= f/f1; + } + } + } + + return x; +} + +// solutions for the cubic equation: a + b*x +c*x^2 + d*x^3 = 0 +// this is a naive implementation of the analytic solution without +// optimisation for speed or numerical accuracy +// newton_iter: number of newton iterations to improve analytical solution +// see also +// gsl: gsl_poly_solve_cubic() in solve_cubic.c +// octave: roots.m - via eigenvalues of the Frobenius companion matrix +std::vector solve_cubic(double a, double b, double c, double d, + int newton_iter) +{ + if(d==0.0) { + return solve_quadratic(a,b,c,newton_iter); + } + + // convert to normalised form: a + bx + cx^2 + x^3 = 0 + if(d!=1.0) { + a/=d; + b/=d; + c/=d; + } + + // convert to depressed cubic: z^3 - 3pz - 2q = 0 + // via substitution: z = x + c/3 + std::vector z; // roots of the depressed cubic + double p = -(1.0/3.0)*b + (1.0/9.0)*(c*c); + double r = 2.0*(c*c)-9.0*b; + double q = -0.5*a - (1.0/54.0)*(c*r); + double discr=p*p*p-q*q; // discriminant + // calculating numerical round-off errors with assumptions: + // - each operation is precise but each intermediate result x + // when stored has max error of x*eps + // - only multiplication with a power of 2 introduces no new error + // - a,b,c,d and some fractions (e.g. 1/3) have rounding errors eps + // - p_err << |p|, q_err << |q|, ... (this is violated in rare cases) + // would be more elegant to use boost::numeric::interval + const double eps = internal::get_eps(); + double p_err = eps*((3.0/3.0)*fabs(b)+(4.0/9.0)*(c*c)+fabs(p)); + double r_err = eps*(6.0*(c*c)+18.0*fabs(b)+fabs(r)); + double q_err = 0.5*fabs(a)*eps + (1.0/54.0)*fabs(c)*(r_err+fabs(r)*3.0*eps) + + fabs(q)*eps; + double discr_err = (p*p) * (3.0*p_err + fabs(p)*2.0*eps) + + fabs(q) * (2.0*q_err + fabs(q)*eps) + fabs(discr)*eps; + + // depending on the discriminant we get different solutions + if(fabs(discr)<=discr_err) { + // discriminant zero: one or two real roots + if(fabs(p)<=p_err) { + // p and q are zero: single root + z.resize(1); + z[0] = 0.0; // triple root + } else { + z.resize(2); + z[0] = 2.0*q/p; // single root + z[1] = -0.5*z[0]; // double root + } + } else if(discr>0) { + // three real roots: via trigonometric solution + z.resize(3); + double ac = (1.0/3.0) * acos( q/(p*sqrt(p)) ); + double sq = 2.0*sqrt(p); + z[0] = sq * cos(ac); + z[1] = sq * cos(ac-2.0*M_PI/3.0); + z[2] = sq * cos(ac-4.0*M_PI/3.0); + } else if (discr<0.0) { + // single real root: via Cardano's fromula + z.resize(1); + double sgnq = (q >= 0 ? 1 : -1); + double basis = fabs(q) + sqrt(-discr); + double C = sgnq * pow(basis, 1.0/3.0); // c++11 has std::cbrt() + z[0] = C + p/C; + } + for(size_t i=0; i1e-8) { + z[i] -= f/f1; + } + } + } + // ensure if a=0 we get exactly x=0 as root + // TODO: remove this fudge + if(a==0.0) { + assert(z.size()>0); // cubic should always have at least one root + double xmin=fabs(z[0]); + size_t imin=0; + for(size_t i=1; ifabs(z[i])) { + xmin=fabs(z[i]); + imin=i; + } + } + z[imin]=0.0; // replace the smallest absolute value with 0 + } + std::sort(z.begin(), z.end()); + return z; +} + + +} // namespace internal + + +} // namespace tk + + +} // namespace + +#if !defined(_MSC_VER) +#pragma GCC diagnostic pop +#endif + +#endif /* TK_SPLINE_H */