vaseweld 1.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- vaseweld-1.3.0/LICENSE +21 -0
- vaseweld-1.3.0/PKG-INFO +393 -0
- vaseweld-1.3.0/README.md +359 -0
- vaseweld-1.3.0/pyproject.toml +62 -0
- vaseweld-1.3.0/setup.cfg +4 -0
- vaseweld-1.3.0/src/vaseweld/__init__.py +5 -0
- vaseweld-1.3.0/src/vaseweld/bgcode.py +307 -0
- vaseweld-1.3.0/src/vaseweld/cli.py +286 -0
- vaseweld-1.3.0/src/vaseweld/compat.py +199 -0
- vaseweld-1.3.0/src/vaseweld/parser.py +475 -0
- vaseweld-1.3.0/src/vaseweld/preview.py +363 -0
- vaseweld-1.3.0/src/vaseweld/validate.py +245 -0
- vaseweld-1.3.0/src/vaseweld/weld.py +849 -0
- vaseweld-1.3.0/src/vaseweld.egg-info/PKG-INFO +393 -0
- vaseweld-1.3.0/src/vaseweld.egg-info/SOURCES.txt +26 -0
- vaseweld-1.3.0/src/vaseweld.egg-info/dependency_links.txt +1 -0
- vaseweld-1.3.0/src/vaseweld.egg-info/entry_points.txt +2 -0
- vaseweld-1.3.0/src/vaseweld.egg-info/requires.txt +8 -0
- vaseweld-1.3.0/src/vaseweld.egg-info/top_level.txt +1 -0
- vaseweld-1.3.0/tests/test_bgcode.py +156 -0
- vaseweld-1.3.0/tests/test_cli.py +238 -0
- vaseweld-1.3.0/tests/test_compat.py +70 -0
- vaseweld-1.3.0/tests/test_hook.py +75 -0
- vaseweld-1.3.0/tests/test_parser.py +129 -0
- vaseweld-1.3.0/tests/test_preview.py +106 -0
- vaseweld-1.3.0/tests/test_single_file.py +52 -0
- vaseweld-1.3.0/tests/test_validate.py +122 -0
- vaseweld-1.3.0/tests/test_weld.py +558 -0
vaseweld-1.3.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Christo Bosch
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
vaseweld-1.3.0/PKG-INFO
ADDED
|
@@ -0,0 +1,393 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: vaseweld
|
|
3
|
+
Version: 1.3.0
|
|
4
|
+
Summary: Weld two G-code files sliced from the same plate so spiral vase mode can start or stop partway up a print.
|
|
5
|
+
Author-email: Christo Bosch <cbosch101@gmail.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/Booyaka101/vaseweld
|
|
8
|
+
Project-URL: Repository, https://github.com/Booyaka101/vaseweld
|
|
9
|
+
Project-URL: Issues, https://github.com/Booyaka101/vaseweld/issues
|
|
10
|
+
Project-URL: Changelog, https://github.com/Booyaka101/vaseweld/blob/main/CHANGELOG.md
|
|
11
|
+
Keywords: 3d-printing,gcode,spiral-vase,vase-mode,prusaslicer,orcaslicer,bambustudio,post-processing,slicer
|
|
12
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
13
|
+
Classifier: Environment :: Console
|
|
14
|
+
Classifier: Intended Audience :: End Users/Desktop
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Operating System :: OS Independent
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
22
|
+
Classifier: Topic :: Printing
|
|
23
|
+
Classifier: Topic :: Utilities
|
|
24
|
+
Requires-Python: >=3.10
|
|
25
|
+
Description-Content-Type: text/markdown
|
|
26
|
+
License-File: LICENSE
|
|
27
|
+
Provides-Extra: dev
|
|
28
|
+
Requires-Dist: pytest>=7; extra == "dev"
|
|
29
|
+
Requires-Dist: ruff; extra == "dev"
|
|
30
|
+
Provides-Extra: docs
|
|
31
|
+
Requires-Dist: pillow; extra == "docs"
|
|
32
|
+
Requires-Dist: numpy; extra == "docs"
|
|
33
|
+
Dynamic: license-file
|
|
34
|
+
|
|
35
|
+
# vaseweld
|
|
36
|
+
|
|
37
|
+
Spiral vase mode is all-or-nothing in every slicer. vaseweld welds two G-code files sliced from
|
|
38
|
+
the same plate at a Z height you pick, so the vase can start above a solid base, or stop below a
|
|
39
|
+
solid lid.
|
|
40
|
+
|
|
41
|
+

|
|
42
|
+
|
|
43
|
+
*Drawn bead by bead from the welded output below, not a photo and not a mock-up. Blue is the normal
|
|
44
|
+
slice, orange is the spiral vase section, and the two seams are at Z=6.2 and Z=30.2. The model is
|
|
45
|
+
`examples/vase_40mm.stl`.*
|
|
46
|
+
|
|
47
|
+
**The output always uses relative extrusion (`M83`).** If your slice uses absolute E (`M82`),
|
|
48
|
+
vaseweld converts it. This is not optional: the flow ramp across the transition layer scales
|
|
49
|
+
extrusion, and a scaled number is only meaningful as a delta. OrcaSlicer's own `SpiralVase.cpp`
|
|
50
|
+
carries the same note, that "Tapering of the transition layer only works reliably with relative
|
|
51
|
+
extruder distances". Any post-processing script you run after vaseweld has to expect relative E.
|
|
52
|
+
|
|
53
|
+
## The problem
|
|
54
|
+
|
|
55
|
+
Slicers put spiral vase behind a single checkbox that applies to the whole print. People have been
|
|
56
|
+
asking for a height range for six years:
|
|
57
|
+
|
|
58
|
+
- PrusaSlicer [#3204](https://github.com/prusa3d/PrusaSlicer/issues/3204), open since November 2019,
|
|
59
|
+
88 reactions, 42 comments. Latest activity is the bot warning it may be auto-closed as a legacy issue.
|
|
60
|
+
- PrusaSlicer [#9340](https://github.com/prusa3d/PrusaSlicer/issues/9340), height range modifiers are
|
|
61
|
+
disabled in vase mode.
|
|
62
|
+
- Cura [#7893](https://github.com/Ultimaker/Cura/issues/7893), open since 2020, 27 comments.
|
|
63
|
+
- OrcaSlicer [#4625](https://github.com/OrcaSlicer/OrcaSlicer/issues/4625), closed as not planned.
|
|
64
|
+
- BambuStudio [#9657](https://github.com/bambulab/BambuStudio/issues/9657), open, someone pointing out
|
|
65
|
+
Simplify3D has done this for years.
|
|
66
|
+
|
|
67
|
+
The workaround people use is to slice twice and paste the files together in a text editor. That gets
|
|
68
|
+
the layer boundary wrong, leaves the extruder in the wrong mode, strands a second start-up sequence
|
|
69
|
+
in the middle of the file, and skips the flow transition the slicer would have done. vaseweld does
|
|
70
|
+
the same job correctly.
|
|
71
|
+
|
|
72
|
+
## Install
|
|
73
|
+
|
|
74
|
+
Pick one. They all produce byte-identical output.
|
|
75
|
+
|
|
76
|
+
```
|
|
77
|
+
pipx run vaseweld weld --help # no install
|
|
78
|
+
uvx vaseweld weld --help # no install
|
|
79
|
+
python -m pip install vaseweld # console script named vaseweld
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Or download a single file that needs nothing but Python 3.10+:
|
|
83
|
+
|
|
84
|
+
```
|
|
85
|
+
curl -LO https://raw.githubusercontent.com/Booyaka101/vaseweld/main/vaseweld.py
|
|
86
|
+
python vaseweld.py weld --help
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Or grab `vaseweld.exe` from the [releases page](https://github.com/Booyaka101/vaseweld/releases) if
|
|
90
|
+
you would rather not have Python at all.
|
|
91
|
+
|
|
92
|
+
## Usage
|
|
93
|
+
|
|
94
|
+
Slice the same plate twice in PrusaSlicer, OrcaSlicer or BambuStudio. Once with Spiral Vase off,
|
|
95
|
+
once with it on. Do not move, rescale or reorient the object in between. Save both files, then:
|
|
96
|
+
|
|
97
|
+
```
|
|
98
|
+
$ vaseweld weld --normal base.gcode --vase body.gcode --at 6.2 -o hybrid.gcode
|
|
99
|
+
note: removed the printing time estimate, which cannot be recomputed from these two files
|
|
100
|
+
cut snapped to Z=6.200 (layer 31)
|
|
101
|
+
normal: layers 1-30 (Z 0.200-6.000)
|
|
102
|
+
vase: layers 31-200 (Z 6.200-40.000)
|
|
103
|
+
E mode: absolute -> relative (converted)
|
|
104
|
+
transition ramp: 0.80 -> 1.00 over layer 31
|
|
105
|
+
wrote hybrid.gcode (31343 lines)
|
|
106
|
+
|
|
107
|
+
$ vaseweld check hybrid.gcode
|
|
108
|
+
OK: Z monotonic, E coherent (relative), retractions balanced, 1 temperature timeline
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
The note goes to stderr; everything else goes to stdout. That run is reproducible from this
|
|
112
|
+
repository. `base.gcode` and `body.gcode` are
|
|
113
|
+
`examples/vase_normal_40mm.gcode` and `examples/vase_spiral_40mm.gcode`, two PrusaSlicer 2.9.6
|
|
114
|
+
slices of `examples/vase_40mm.stl` at 0.2 mm layers.
|
|
115
|
+
|
|
116
|
+
`--at` is a height in millimetres, not a layer number. It snaps down to the nearest real layer and
|
|
117
|
+
tells you which one:
|
|
118
|
+
|
|
119
|
+
```
|
|
120
|
+
$ vaseweld weld --normal base.gcode --vase body.gcode --at 6.3 -o hybrid.gcode
|
|
121
|
+
requested Z=6.300 is between layers, snapping down
|
|
122
|
+
cut snapped to Z=6.200 (layer 31)
|
|
123
|
+
...
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Repeat `--at` to alternate again. Two cuts give the shape people actually ask for, a solid base, a
|
|
127
|
+
vase body and a solid lid:
|
|
128
|
+
|
|
129
|
+
```
|
|
130
|
+
$ vaseweld weld --normal base.gcode --vase body.gcode --at 6.2 --at 30.2 -o hybrid.gcode
|
|
131
|
+
cuts snapped to Z=6.200 (layer 31), Z=30.200 (layer 151)
|
|
132
|
+
normal: layers 1-30 (Z 0.200-6.000)
|
|
133
|
+
vase: layers 31-150 (Z 6.200-30.000)
|
|
134
|
+
normal: layers 151-200 (Z 30.200-40.000)
|
|
135
|
+
E mode: absolute -> relative (converted)
|
|
136
|
+
transition ramp: 0.80 -> 1.00 over layer 31
|
|
137
|
+
transition ramp: 1.00 -> 0.25 over layer 150
|
|
138
|
+
wrote hybrid.gcode (45013 lines)
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Every seam gets its own travel, retraction match and flow ramp, so the spiral ramps up where it
|
|
142
|
+
starts and back down where it ends.
|
|
143
|
+
|
|
144
|
+
If you would rather not guess at the cut height, ask:
|
|
145
|
+
|
|
146
|
+
```
|
|
147
|
+
$ vaseweld layers body.gcode
|
|
148
|
+
vase_spiral_40mm.gcode: 200 layers, Z 0.200 to 40.000
|
|
149
|
+
layer height: 0.200 mm
|
|
150
|
+
weldable range: Z 0.400 to 40.000 (layers 2 to 200)
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
`--vase-first` inverts the order, for a vase body with a solid lid on top:
|
|
154
|
+
|
|
155
|
+
```
|
|
156
|
+
$ vaseweld weld --normal base.gcode --vase body.gcode --at 30.2 --vase-first -o hybrid.gcode
|
|
157
|
+
cut snapped to Z=30.200 (layer 151)
|
|
158
|
+
vase: layers 1-150 (Z 0.200-30.000)
|
|
159
|
+
normal: layers 151-200 (Z 30.200-40.000)
|
|
160
|
+
E mode: absolute -> relative (converted)
|
|
161
|
+
transition ramp: 1.00 -> 0.25 over layer 150
|
|
162
|
+
wrote hybrid.gcode (35289 lines)
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
OrcaSlicer files already use relative E, so nothing is converted, and the flow ratios come from the
|
|
166
|
+
file's own config block:
|
|
167
|
+
|
|
168
|
+
```
|
|
169
|
+
$ vaseweld weld --normal orca_base.gcode --vase orca_body.gcode --at 12.4 -o hybrid.gcode
|
|
170
|
+
cut snapped to Z=12.400 (layer 62)
|
|
171
|
+
normal: layers 1-61 (Z 0.200-12.200)
|
|
172
|
+
vase: layers 62-200 (Z 12.400-40.000)
|
|
173
|
+
E mode: relative (unchanged)
|
|
174
|
+
transition ramp: 0.00 -> 1.00 over layer 62
|
|
175
|
+
wrote hybrid.gcode (25647 lines)
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
`0.00` there is OrcaSlicer's shipped default for `spiral_starting_flow_ratio`, which is what Orca
|
|
179
|
+
itself would ramp from. If that under-extrudes at the seam, pass `--start-flow 0.8`.
|
|
180
|
+
|
|
181
|
+
## Running it from the slicer
|
|
182
|
+
|
|
183
|
+
You can let the slicer call vaseweld on the file it just wrote. Put this in
|
|
184
|
+
**Print settings > Output options > Post-processing scripts** on the profile that has Spiral Vase
|
|
185
|
+
turned on:
|
|
186
|
+
|
|
187
|
+
```
|
|
188
|
+
"C:\Program Files\vaseweld\vaseweld.exe" weld --normal "C:\prints\base.gcode" --at 12.4
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
The slicer appends the absolute path of a temporary G-code file as the last argument. vaseweld takes
|
|
192
|
+
that file as whichever side you left out, here the vase side, and rewrites it in place. It also
|
|
193
|
+
reads `SLIC3R_PP_OUTPUT_NAME`, the name the slicer will save under, and prints it so you can see
|
|
194
|
+
where the file is going.
|
|
195
|
+
|
|
196
|
+
Two things to watch. Use absolute paths and quote them, because the field is not a shell. And turn
|
|
197
|
+
off **Supports binary G-code** in the same Output options panel. vaseweld reads `.bgcode` fine, but
|
|
198
|
+
it writes plain G-code, so it will not overwrite a `.bgcode` file the slicer is about to save under
|
|
199
|
+
that name. Printers that accept `.bgcode` accept plain G-code too.
|
|
200
|
+
|
|
201
|
+
## What it actually does
|
|
202
|
+
|
|
203
|
+
- Splits both files into header, layers keyed by Z, and footer, using the `;LAYER_CHANGE` and `;Z:`
|
|
204
|
+
markers that PrusaSlicer, OrcaSlicer and BambuStudio all emit, and falling back to bare Z moves.
|
|
205
|
+
- Refuses the weld unless both files agree on `layer_height`, `first_layer_height`,
|
|
206
|
+
`nozzle_diameter`, `filament_diameter`, `bed_shape`, `printer_model`, the object instance count,
|
|
207
|
+
and where the object sits on the bed. A mismatch names the field.
|
|
208
|
+
- Emits relative E throughout, converting absolute-E segments by differencing consecutive values,
|
|
209
|
+
and resets with `G92 E0` at the seam.
|
|
210
|
+
- Ramps the flow across the transition layer the way the slicer would, from
|
|
211
|
+
`spiral_starting_flow_ratio` up to 1.0 across the first vase layer, or from 1.0 down to
|
|
212
|
+
`spiral_finishing_flow_ratio` across the last one. Fallbacks are 0.8 and 0.25 when the key is
|
|
213
|
+
absent, as it is in PrusaSlicer.
|
|
214
|
+
- Travels to where the vase slice expects the nozzle, and matches the retraction state that slice
|
|
215
|
+
assumes. A vase layer takes for granted that the nozzle is already on its spiral, because in the
|
|
216
|
+
source file the previous layer ended there. Without the travel the first spiral move drags a line
|
|
217
|
+
across the print. The retraction part matters because slicers disagree about who owns the
|
|
218
|
+
layer-change retraction: PrusaSlicer and OrcaSlicer put it at the start of the next layer,
|
|
219
|
+
BambuStudio at the end of the previous one, so welding them naively leaves the nozzle either
|
|
220
|
+
double-retracted or double-primed.
|
|
221
|
+
- Rewrites Klipper's `SET_PRINT_STATS_INFO TOTAL_LAYER` and `CURRENT_LAYER`, the
|
|
222
|
+
`total layers count` comments, and BambuStudio's `HEADER_BLOCK` totals.
|
|
223
|
+
- Recomputes the filament totals exactly, and remaps `M73` progress and the printing time estimate
|
|
224
|
+
using the two files' own remaining-time values. When there is no `M73` data to remap from, it
|
|
225
|
+
strips the time comments rather than leave them wrong.
|
|
226
|
+
- Reads binary G-code (`.bgcode`) as well as text, decoding it in the tool with no converter on
|
|
227
|
+
PATH and no dependencies. Binarising moves the config block and the filament and time totals out
|
|
228
|
+
of the G-code stream into metadata blocks, so they are put back where a text file would have had
|
|
229
|
+
them and everything downstream works unchanged. The trailing comment on each command
|
|
230
|
+
(`G28 ; home all axes`) is gone for good; the binariser drops it.
|
|
231
|
+
- Passes `G2`/`G3` arc moves through with their geometry untouched. Their E values are still
|
|
232
|
+
converted, because leaving them absolute in a relative file would break the print.
|
|
233
|
+
- Writes a `; vaseweld` provenance block into the header naming both inputs and the cut.
|
|
234
|
+
|
|
235
|
+
## See it without a printer
|
|
236
|
+
|
|
237
|
+
**[Open the demo](https://booyaka101.github.io/vaseweld/)** and drag the slider. Three welds of the same pair of slices, drawn from
|
|
238
|
+
their real G-code, nothing to install.
|
|
239
|
+
|
|
240
|
+
`vaseweld preview` writes the same thing for your own file, one self-contained HTML file. Open it in any browser and drag the slider:
|
|
241
|
+
every bead is drawn at the width the G-code actually asks for, coloured by which slice it came from.
|
|
242
|
+
|
|
243
|
+
```
|
|
244
|
+
$ vaseweld preview hybrid.gcode
|
|
245
|
+
wrote hybrid.html (418 KB), open it in any browser
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+

|
|
249
|
+
|
|
250
|
+
That is layer 31 of the two-cut weld, from above. The ghosted blue underneath is the last normal
|
|
251
|
+
layer, walls and gyroid infill; the orange loop on top is the first spiral layer. The front view
|
|
252
|
+
builds up as you scrub, which is the image at the top of this page.
|
|
253
|
+
|
|
254
|
+
To rebuild that demo from a fresh clone, with nothing installed:
|
|
255
|
+
|
|
256
|
+
```
|
|
257
|
+
python sim/demo.py
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
That welds the two committed example slices three ways, runs `vaseweld check` on each, and writes
|
|
261
|
+
`docs/demo/index.html` linking the three previews.
|
|
262
|
+
|
|
263
|
+
## Proof it prints
|
|
264
|
+
|
|
265
|
+
The unit tests prove the output is well formed. `sim/` proves a printer would accept it, by feeding
|
|
266
|
+
every case to **Klipper's own host process in batch mode**, which plans each move through the real
|
|
267
|
+
cartesian kinematics and the real extruder limits with no printer attached.
|
|
268
|
+
|
|
269
|
+
```
|
|
270
|
+
docker build -t klipper-batch sim/ && python sim/build_cases.py
|
|
271
|
+
docker run --rm -v "$PWD/sim:/work" klipper-batch bash /work/run.sh
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
```
|
|
275
|
+
PASS 1_absolute_source_normal print time 368.737s
|
|
276
|
+
PASS 1_absolute_source_vase print time 305.882s
|
|
277
|
+
FAIL 2_absolute_naive_text_editor klippy exit 255, 40 rejected moves
|
|
278
|
+
Move exceeds maximum extrusion (10.116mm^2 vs 0.640mm^2)
|
|
279
|
+
PASS 2_relative_naive_text_editor print time 304.025s
|
|
280
|
+
PASS 3_absolute_vaseweld print time 299.385s
|
|
281
|
+
PASS 3_relative_vaseweld print time 299.512s
|
|
282
|
+
PASS 4_absolute_vaseweld_vase_first print time 371.931s
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
`2_naive_text_editor` is the workaround people use today: paste the two files together at a layer
|
|
286
|
+
boundary. With absolute E, which is PrusaSlicer's default, the printer refuses it, because every E
|
|
287
|
+
value after the paste is read as an absolute position. With relative E it plans fine but still prints
|
|
288
|
+
a 12.5 mm scar, because the nozzle is left where the other file stopped and the spiral starts
|
|
289
|
+
somewhere else:
|
|
290
|
+
|
|
291
|
+
| first move after the cut | travel | filament | flow vs normal |
|
|
292
|
+
| --- | --- | --- | --- |
|
|
293
|
+
| hand splice, absolute E | 12.522 mm | 33.03150 mm | 7794% |
|
|
294
|
+
| hand splice, relative E | 12.522 mm | 0.01694 mm | 4% |
|
|
295
|
+
| vaseweld, either | 0.500 mm | 0.01359 mm | 80.2% |
|
|
296
|
+
|
|
297
|
+
That 80.2% is the transition ramp starting from `--start-flow 0.8`.
|
|
298
|
+
|
|
299
|
+
`sim/deposit.py` takes it the rest of the way: it turns every extruding move into a bead of known
|
|
300
|
+
width and draws the weld layer from above, so you can see what the two files put on the plate.
|
|
301
|
+
|
|
302
|
+

|
|
303
|
+
|
|
304
|
+
The red line is a real extrusion, 0.06 mm wide, laid straight across the open middle of the vase.
|
|
305
|
+
That is what a hand splice does at the seam, because the nozzle is still where the other file left
|
|
306
|
+
it. The same model sawn through the wall:
|
|
307
|
+
|
|
308
|
+

|
|
309
|
+
|
|
310
|
+
Bead widths at the weld layer, against a 0.450 mm nominal:
|
|
311
|
+
|
|
312
|
+
| | hand splice | vaseweld |
|
|
313
|
+
| --- | --- | --- |
|
|
314
|
+
| the wall | 0.450 mm, no ramp | 0.425 mm, the ramp starting at 80% |
|
|
315
|
+
| across the part | 0.059 mm thread | nothing |
|
|
316
|
+
|
|
317
|
+
`tests/test_weld.py` carries this as a regression guard: no printing move at the weld layer may lay
|
|
318
|
+
a bead outside half to twice the layer's own nominal width, checked for all three slicers, with a
|
|
319
|
+
companion test that the same measurement does catch a hand splice. See [sim/README.md](sim/README.md).
|
|
320
|
+
|
|
321
|
+
## The other commands
|
|
322
|
+
|
|
323
|
+
`vaseweld layers FILE` prints the Z ladder and the weldable range.
|
|
324
|
+
`vaseweld preview FILE` writes the HTML page above.
|
|
325
|
+
`vaseweld check FILE` works on any G-code file, welded or not. It runs four checks:
|
|
326
|
+
|
|
327
|
+
| check | what it catches |
|
|
328
|
+
| --- | --- |
|
|
329
|
+
| Z monotonic | an extruding move below a height already printed, the classic bad splice |
|
|
330
|
+
| E coherent | an absolute E value stranded in a relative file, or a mid-print `M82`/`M83` switch |
|
|
331
|
+
| retractions balanced | more filament pulled back at once than one retraction's worth, which means an unretract went missing |
|
|
332
|
+
| temperature timeline | a blocking `M109`/`M190` in the middle of the print, which is the start-up sequence of a second file |
|
|
333
|
+
|
|
334
|
+
Exit codes are 0 for OK, 1 for problems found, 2 for a file it could not read.
|
|
335
|
+
|
|
336
|
+
```
|
|
337
|
+
$ vaseweld check broken.gcode
|
|
338
|
+
FAIL: 1 problem in broken.gcode
|
|
339
|
+
line 12695: blocking temperature wait (M109 S215) in the middle of the print; this is the start-up sequence of a second file
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
## Options
|
|
343
|
+
|
|
344
|
+
`vaseweld weld` takes:
|
|
345
|
+
|
|
346
|
+
```
|
|
347
|
+
--normal PATH the non-vase slice
|
|
348
|
+
--vase PATH the spiral vase slice
|
|
349
|
+
--at Z cut height in mm, snapped down to a real layer; repeat to alternate again
|
|
350
|
+
-o, --output PATH file to write
|
|
351
|
+
--vase-first start with the vase part below the first cut
|
|
352
|
+
--start-flow RATIO override spiral_starting_flow_ratio (0 to 1)
|
|
353
|
+
--finish-flow RATIO override spiral_finishing_flow_ratio (0 to 1)
|
|
354
|
+
--no-seam-retract do not retract before the seam travel
|
|
355
|
+
--dry-run report the plan and write nothing
|
|
356
|
+
--force weld despite a profile mismatch, and say what was ignored
|
|
357
|
+
and what that does to the seam
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
## Limitations
|
|
361
|
+
|
|
362
|
+
These are out of scope for 1.0, not bugs:
|
|
363
|
+
|
|
364
|
+
- Binary `.bgcode` can be read but not written. The output is always text G-code.
|
|
365
|
+
- Single object, single material. This is the same constraint PrusaSlicer's own validator enforces,
|
|
366
|
+
and vaseweld quotes it back at you: "The Spiral Vase option can only be used when printing single
|
|
367
|
+
material objects."
|
|
368
|
+
- vaseweld does not slice. You bring both files.
|
|
369
|
+
- The printing time estimate can only be recomputed when the files carry `M73` remaining times,
|
|
370
|
+
which PrusaSlicer emits only with "Supports remaining times" enabled. Otherwise the estimate is
|
|
371
|
+
stripped.
|
|
372
|
+
- Adaptive or variable layer height will make the two files disagree on layer Z. Slice both with a
|
|
373
|
+
fixed layer height.
|
|
374
|
+
|
|
375
|
+
## Development
|
|
376
|
+
|
|
377
|
+
```
|
|
378
|
+
git clone https://github.com/Booyaka101/vaseweld
|
|
379
|
+
cd vaseweld
|
|
380
|
+
python -m pytest
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
138 tests, about 40 seconds, no dependencies beyond pytest. Everything runs against real slicer
|
|
384
|
+
output committed under `tests/fixtures/`, produced by driving PrusaSlicer 2.9.6, OrcaSlicer 2.4.2
|
|
385
|
+
and BambuStudio 02.08.02.61 from the command line over the models in `examples/`. See
|
|
386
|
+
[tests/fixtures/README.md](tests/fixtures/README.md) for the exact commands.
|
|
387
|
+
|
|
388
|
+
`vaseweld.py` at the repository root is generated from `src/vaseweld/` by
|
|
389
|
+
`python tools/build_single_file.py`. A test fails if it drifts.
|
|
390
|
+
|
|
391
|
+
## License
|
|
392
|
+
|
|
393
|
+
MIT.
|