svg2gcode 3.3.0__tar.gz → 3.3.2__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.
- {svg2gcode-3.3.0 → svg2gcode-3.3.2}/PKG-INFO +1 -1
- {svg2gcode-3.3.0 → svg2gcode-3.3.2}/svg2gcode/__init__.py +1 -1
- {svg2gcode-3.3.0 → svg2gcode-3.3.2}/svg2gcode/svg_to_gcode/compiler/_compiler.py +72 -42
- {svg2gcode-3.3.0 → svg2gcode-3.3.2}/svg2gcode/svg_to_gcode/compiler/interfaces/_gcode.py +7 -7
- {svg2gcode-3.3.0 → svg2gcode-3.3.2}/LICENSE +0 -0
- {svg2gcode-3.3.0 → svg2gcode-3.3.2}/README.md +0 -0
- {svg2gcode-3.3.0 → svg2gcode-3.3.2}/pyproject.toml +0 -0
- {svg2gcode-3.3.0 → svg2gcode-3.3.2}/svg2gcode/__main__.py +0 -0
- {svg2gcode-3.3.0 → svg2gcode-3.3.2}/svg2gcode/svg_to_gcode/LICENSE +0 -0
- {svg2gcode-3.3.0 → svg2gcode-3.3.2}/svg2gcode/svg_to_gcode/__init__.py +0 -0
- {svg2gcode-3.3.0 → svg2gcode-3.3.2}/svg2gcode/svg_to_gcode/compiler/__init__.py +0 -0
- {svg2gcode-3.3.0 → svg2gcode-3.3.2}/svg2gcode/svg_to_gcode/compiler/interfaces/__init__.py +0 -0
- {svg2gcode-3.3.0 → svg2gcode-3.3.2}/svg2gcode/svg_to_gcode/compiler/interfaces/_abstract_interface.py +0 -0
- {svg2gcode-3.3.0 → svg2gcode-3.3.2}/svg2gcode/svg_to_gcode/compiler/interfaces/_fan_controlled_gcode.py +0 -0
- {svg2gcode-3.3.0 → svg2gcode-3.3.2}/svg2gcode/svg_to_gcode/css_color.py +0 -0
- {svg2gcode-3.3.0 → svg2gcode-3.3.2}/svg2gcode/svg_to_gcode/formulas.py +0 -0
- {svg2gcode-3.3.0 → svg2gcode-3.3.2}/svg2gcode/svg_to_gcode/geometry/__init__.py +0 -0
- {svg2gcode-3.3.0 → svg2gcode-3.3.2}/svg2gcode/svg_to_gcode/geometry/_abstract_chain.py +0 -0
- {svg2gcode-3.3.0 → svg2gcode-3.3.2}/svg2gcode/svg_to_gcode/geometry/_abstract_curve.py +0 -0
- {svg2gcode-3.3.0 → svg2gcode-3.3.2}/svg2gcode/svg_to_gcode/geometry/_circular_arc.py +0 -0
- {svg2gcode-3.3.0 → svg2gcode-3.3.2}/svg2gcode/svg_to_gcode/geometry/_cubic_bazier.py +0 -0
- {svg2gcode-3.3.0 → svg2gcode-3.3.2}/svg2gcode/svg_to_gcode/geometry/_elliptical_arc.py +0 -0
- {svg2gcode-3.3.0 → svg2gcode-3.3.2}/svg2gcode/svg_to_gcode/geometry/_line.py +0 -0
- {svg2gcode-3.3.0 → svg2gcode-3.3.2}/svg2gcode/svg_to_gcode/geometry/_line_segment_chain.py +0 -0
- {svg2gcode-3.3.0 → svg2gcode-3.3.2}/svg2gcode/svg_to_gcode/geometry/_matrix.py +0 -0
- {svg2gcode-3.3.0 → svg2gcode-3.3.2}/svg2gcode/svg_to_gcode/geometry/_quadratic_bazier.py +0 -0
- {svg2gcode-3.3.0 → svg2gcode-3.3.2}/svg2gcode/svg_to_gcode/geometry/_raster_image.py +0 -0
- {svg2gcode-3.3.0 → svg2gcode-3.3.2}/svg2gcode/svg_to_gcode/geometry/_smooth_arc_chain.py +0 -0
- {svg2gcode-3.3.0 → svg2gcode-3.3.2}/svg2gcode/svg_to_gcode/geometry/_vector.py +0 -0
- {svg2gcode-3.3.0 → svg2gcode-3.3.2}/svg2gcode/svg_to_gcode/svg_parser/__init__.py +0 -0
- {svg2gcode-3.3.0 → svg2gcode-3.3.2}/svg2gcode/svg_to_gcode/svg_parser/_parser_methods.py +0 -0
- {svg2gcode-3.3.0 → svg2gcode-3.3.2}/svg2gcode/svg_to_gcode/svg_parser/_path.py +0 -0
- {svg2gcode-3.3.0 → svg2gcode-3.3.2}/svg2gcode/svg_to_gcode/svg_parser/_transformation.py +0 -0
- {svg2gcode-3.3.0 → svg2gcode-3.3.2}/svg2gcode/svg_to_gcode/svg_parser/debug_methods.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: svg2gcode
|
|
3
|
-
Version: 3.3.
|
|
3
|
+
Version: 3.3.2
|
|
4
4
|
Summary: svg2gcode: convert an SVG (Scalable Vector Graphic) image to gcode.
|
|
5
5
|
Keywords: scalable vector graphics,svg,image,laser cutter,laser engraving
|
|
6
6
|
Author-email: Johannes Noordanus <mailjohannes.mailnoordanus@gmail.com>
|
|
@@ -66,6 +66,9 @@ class Compiler:
|
|
|
66
66
|
|
|
67
67
|
self.interface.set_machine_parameters(self.settings)
|
|
68
68
|
|
|
69
|
+
# toggle
|
|
70
|
+
self.fan_on = self.settings['fan']
|
|
71
|
+
|
|
69
72
|
if custom_header is None:
|
|
70
73
|
custom_header = []
|
|
71
74
|
|
|
@@ -77,7 +80,7 @@ class Compiler:
|
|
|
77
80
|
self.interface.set_distance_mode(self.settings["distance_mode"])] + custom_header
|
|
78
81
|
self.footer = custom_footer
|
|
79
82
|
|
|
80
|
-
# path
|
|
83
|
+
# path gcode
|
|
81
84
|
self.body: list[str] = []
|
|
82
85
|
# image gcode
|
|
83
86
|
self.gcode: list[str] = []
|
|
@@ -128,12 +131,13 @@ class Compiler:
|
|
|
128
131
|
|
|
129
132
|
:param passes: the number of passes that should be made. Every pass the machine moves_down (z-axis) by
|
|
130
133
|
self.pass_depth and self.body is repeated.
|
|
131
|
-
:return returns the assembled code.
|
|
134
|
+
:return returns the assembled g-code. [self.body, -self.pass_depth] * passes
|
|
132
135
|
"""
|
|
133
136
|
if len(self.body) == 0:
|
|
134
137
|
logger.debug("Compile with an empty body (no curves).")
|
|
135
138
|
return ''
|
|
136
139
|
|
|
140
|
+
fan_off = False
|
|
137
141
|
gcode = []
|
|
138
142
|
for i in range(passes):
|
|
139
143
|
gcode += [f"; pass #{i+1}"]
|
|
@@ -141,13 +145,11 @@ class Compiler:
|
|
|
141
145
|
|
|
142
146
|
if i < (passes - 1) and self.settings["pass_depth"] > 0:
|
|
143
147
|
# If it isn't the last pass, turn off the laser and move down
|
|
144
|
-
gcode.append(self.interface.laser_off())
|
|
148
|
+
gcode.append(self.interface.laser_off(fan_off))
|
|
145
149
|
gcode.append(self.interface.set_relative_coordinates())
|
|
146
150
|
gcode.append(self.interface.linear_move(z=-self.settings["pass_depth"]))
|
|
147
151
|
gcode.append(self.interface.set_distance_mode(self.settings["distance_mode"]))
|
|
148
152
|
|
|
149
|
-
gcode += [self.interface.laser_off()]
|
|
150
|
-
|
|
151
153
|
# remove all ""
|
|
152
154
|
gcode = filter(lambda command: len(command) > 0, gcode)
|
|
153
155
|
|
|
@@ -160,11 +162,12 @@ class Compiler:
|
|
|
160
162
|
"""
|
|
161
163
|
|
|
162
164
|
# laser off, fan on, M3 or M4 burn mode
|
|
163
|
-
header_gc = ["M5"
|
|
164
|
-
|
|
165
|
-
|
|
165
|
+
header_gc = ["M5"]
|
|
166
|
+
if self.settings['fan'] and self.settings["splitfile"]:
|
|
167
|
+
header_gc += ['M8']
|
|
168
|
+
header_gc += ['M3' if self.settings["laser_mode"] == "constant" else 'M4']
|
|
166
169
|
|
|
167
|
-
return '\n'.join(header_gc + self.gcode
|
|
170
|
+
return '\n'.join(header_gc + self.gcode)
|
|
168
171
|
|
|
169
172
|
def compile_to_file(self, file_name: str, svg_file_name: str, curves: list[Curve], passes=1):
|
|
170
173
|
"""
|
|
@@ -182,15 +185,17 @@ class Compiler:
|
|
|
182
185
|
self.append_curves(curves)
|
|
183
186
|
|
|
184
187
|
header = '\n'.join(self.header) + '\n'
|
|
188
|
+
footer = '\n'.join(self.footer) + '\n'
|
|
185
189
|
|
|
186
190
|
if len(self.body) > 0:
|
|
187
191
|
# write path objects
|
|
188
192
|
with open(file_name, 'w') as file:
|
|
189
|
-
emit_program_end = self.interface.program_end() if (self.settings["splitfile"] or len(self.gcode) == 0) else ""
|
|
190
|
-
|
|
193
|
+
#emit_program_end = self.interface.program_end() if (self.settings["splitfile"] or len(self.gcode) == 0) else ""
|
|
194
|
+
program_end = footer if (self.settings["splitfile"] or len(self.gcode) == 0) else ""
|
|
195
|
+
file.write(self.gcode_file_header() + header + self.compile(passes=passes) + '\n' + program_end)
|
|
191
196
|
logger.info(f"Generated {file_name}")
|
|
192
197
|
else:
|
|
193
|
-
logger.warn(f'No path (curve) data found
|
|
198
|
+
logger.warn(f'No path (curve) data found nothing added to "{file_name}"')
|
|
194
199
|
|
|
195
200
|
image_file_name = file_name.rsplit('.',1)[0] + "_images." + file_name.rsplit('.',1)[1]
|
|
196
201
|
if len(self.gcode) == 0:
|
|
@@ -202,13 +207,13 @@ class Compiler:
|
|
|
202
207
|
if self.settings["splitfile"]:
|
|
203
208
|
# emit image objects to <filename>_images.<gcext>
|
|
204
209
|
with open(image_file_name, 'w') as file:
|
|
205
|
-
file.write(self.gcode_file_header() + header +
|
|
210
|
+
file.write(self.gcode_file_header() + header + self.compile_images() + '\n' + footer)
|
|
206
211
|
logger.info(f"Generated {image_file_name}")
|
|
207
212
|
else:
|
|
208
213
|
# emit images objects in same file
|
|
209
214
|
open_mode = 'w' if len(self.body) == 0 else 'a+'
|
|
210
215
|
with open(file_name, open_mode) as file:
|
|
211
|
-
file.write((self.gcode_file_header() if len(self.body) == 0 else "") + '\n' + self.compile_images() + '\n' +
|
|
216
|
+
file.write((self.gcode_file_header() if len(self.body) == 0 else "") + '\n' + self.compile_images() + '\n' + footer)
|
|
212
217
|
logger.info(f"Added image(s) to {file_name}")
|
|
213
218
|
|
|
214
219
|
def append_line_chain(self, line_chain: LineSegmentChain, step: float, color: int = None, speed: int = None):
|
|
@@ -233,20 +238,24 @@ class Compiler:
|
|
|
233
238
|
laser_power = color if color is not None else self.settings["laser_power"]
|
|
234
239
|
movement_speed = speed if speed is not None else self.settings["movement_speed"]
|
|
235
240
|
|
|
241
|
+
# do not turn fan off
|
|
242
|
+
fan_off = False
|
|
243
|
+
|
|
236
244
|
# Move to the next line_chain when the next line segment doesn't connect to the end of the previous one.
|
|
237
245
|
if self.interface.position is None or abs(self.interface.position - start) > TOLERANCES["operation"]:
|
|
238
246
|
if self.interface.position is None or self.settings["rapid_move"]:
|
|
239
247
|
# move to the next line_chain: set laser off, rapid move to start of chain,
|
|
240
248
|
# set movement (cutting) speed, set laser mode and power on
|
|
241
|
-
code += [self.interface.laser_off(), self.interface.rapid_move(start.x, start.y),
|
|
249
|
+
code += [self.interface.laser_off(fan_off), self.interface.rapid_move(start.x, start.y),
|
|
242
250
|
self.interface.set_movement_speed(movement_speed),
|
|
243
|
-
self.interface.set_laser_mode(self.settings["laser_mode"]), self.interface.set_laser_power_value(laser_power)]
|
|
251
|
+
self.interface.set_laser_mode(self.settings["laser_mode"]), self.interface.set_laser_power_value(laser_power,self.fan_on)]
|
|
244
252
|
else:
|
|
245
253
|
# move to the next line_chain: set laser mode, set laser power to 0 (cutting is off),
|
|
246
254
|
# set movement speed, (no rapid) move to start of chain, set laser to power
|
|
247
|
-
code += [self.interface.set_laser_mode(self.settings["laser_mode"]), self.interface.set_laser_power_value(0),
|
|
255
|
+
code += [self.interface.set_laser_mode(self.settings["laser_mode"]), self.interface.set_laser_power_value(0,self.fan_on),
|
|
248
256
|
self.interface.set_movement_speed(movement_speed), self.interface.linear_move(start.x, start.y),
|
|
249
257
|
self.interface.set_laser_power_value(laser_power)]
|
|
258
|
+
self.fan_on = False
|
|
250
259
|
|
|
251
260
|
self.boundingbox.update(start)
|
|
252
261
|
|
|
@@ -370,7 +379,7 @@ class Compiler:
|
|
|
370
379
|
arguments["showoverscan"] = img_attrib['gcode_showoverscan'] if 'gcode_showoverscan' in img_attrib else self.settings["image_showoverscan"]
|
|
371
380
|
arguments["offset"] = (float(img_attrib['x']), float(img_attrib['y']))
|
|
372
381
|
arguments["name"] = img_attrib['id']
|
|
373
|
-
arguments["invert"] = img_attrib['invert'] if 'invert' in img_attrib else
|
|
382
|
+
arguments["invert"] = img_attrib['invert'] if 'invert' in img_attrib else True
|
|
374
383
|
|
|
375
384
|
# get image parameters
|
|
376
385
|
params = ''
|
|
@@ -671,7 +680,10 @@ class Compiler:
|
|
|
671
680
|
# Invert b&w value and apply alpha channel - when available - to the inverted b&w value
|
|
672
681
|
# Library function image2gcode - as it is now - cannot invert a color value and then apply the alpha channel.
|
|
673
682
|
# Note that step 6 of '# Render svg fill attribute' below, sets option 'invert' of image2gcode to false to use fill_color directly.)
|
|
674
|
-
|
|
683
|
+
|
|
684
|
+
# invert (byte value)
|
|
685
|
+
fill_color = Image2gcode.linear_power(css_color.parse_css_color2bw8(style['fill']), 255)
|
|
686
|
+
|
|
675
687
|
if style['fill-rule'] is not None:
|
|
676
688
|
fill_rule = style['fill-rule']
|
|
677
689
|
if fill_rule == "nonzero":
|
|
@@ -687,7 +699,7 @@ class Compiler:
|
|
|
687
699
|
fill_alpha = 1
|
|
688
700
|
if len(rgba) == 4:
|
|
689
701
|
fill_alpha = rgba[3]
|
|
690
|
-
fill_color = fill_color * fill_alpha
|
|
702
|
+
fill_color = round(fill_color * fill_alpha)
|
|
691
703
|
|
|
692
704
|
return (stroke_width, stroke_color, stroke_alpha, fill_color, fill_alpha, fill_rule)
|
|
693
705
|
|
|
@@ -747,14 +759,6 @@ class Compiler:
|
|
|
747
759
|
stroke_width, stroke_color, stroke_alpha, fill_color, fill_alpha, fill_rule = get_style_info_of_line_chain(line_chain)
|
|
748
760
|
|
|
749
761
|
if len(stroke_color):
|
|
750
|
-
# Get steps (offsets) for the lines that make the border
|
|
751
|
-
steps = [0]
|
|
752
|
-
if stroke_width:
|
|
753
|
-
for delta in range(stroke_width):
|
|
754
|
-
if delta:
|
|
755
|
-
steps.append(round(delta * pixel_size, self.precision))
|
|
756
|
-
if not (delta == stroke_width and stroke_width % 2 != 0):
|
|
757
|
-
steps.append(round(-delta * pixel_size, self.precision))
|
|
758
762
|
|
|
759
763
|
# Get stroke alpha channel (opacity)
|
|
760
764
|
# fill opacity attribute overrides rgba property
|
|
@@ -766,8 +770,8 @@ class Compiler:
|
|
|
766
770
|
|
|
767
771
|
# engrave values
|
|
768
772
|
# set inversed b&w value (and apply alpha channel, when available)
|
|
769
|
-
inverse_bw = Image2gcode.linear_power(css_color.parse_css_color2bw8(stroke_color),
|
|
770
|
-
self.settings["maximum_image_laser_power"]) * stroke_alpha
|
|
773
|
+
inverse_bw = round(Image2gcode.linear_power(css_color.parse_css_color2bw8(stroke_color),
|
|
774
|
+
self.settings["maximum_image_laser_power"]) * stroke_alpha)
|
|
771
775
|
# set laser head movement speed
|
|
772
776
|
speed = self.settings["image_movement_speed"]
|
|
773
777
|
|
|
@@ -782,31 +786,51 @@ class Compiler:
|
|
|
782
786
|
# color_coded set cut path for this stroke_color
|
|
783
787
|
self.body.extend([f"\n; --color_coded cut path '{name_id}', color '{stroke_color}'"])
|
|
784
788
|
render_pathwidth(line_chain, [0], None, None, boundingbox)
|
|
785
|
-
|
|
786
|
-
#
|
|
787
|
-
pathignore, pathcut, pathengrave = color_coded_paths()
|
|
789
|
+
elif inverse_bw:
|
|
790
|
+
# with path color, setengrave path ...
|
|
791
|
+
pathignore, pathcut, pathengrave = self.color_coded_paths()
|
|
788
792
|
|
|
789
793
|
# ... if color_coded did not set engrave (at all) or set engrave for this stroke_color
|
|
790
794
|
if len(pathengrave) == 0 or engravepath:
|
|
795
|
+
# Get steps (offsets) for the lines that make the border
|
|
796
|
+
steps = [0]
|
|
797
|
+
if stroke_width:
|
|
798
|
+
for delta in range(stroke_width):
|
|
799
|
+
if delta:
|
|
800
|
+
steps.append(round(delta * pixel_size, self.precision))
|
|
801
|
+
if not (delta == stroke_width and stroke_width % 2 != 0):
|
|
802
|
+
steps.append(round(-delta * pixel_size, self.precision))
|
|
803
|
+
|
|
791
804
|
if len(pathengrave) == 0:
|
|
792
805
|
self.body.extend([f"\n; --color_coded: engrave not set, path '{name_id}', color '{stroke_color}'"])
|
|
793
806
|
else:
|
|
794
807
|
self.body.extend([f"\n; --color_coded: engrave path '{name_id}', color '{stroke_color}'"])
|
|
795
808
|
render_pathwidth(line_chain, steps, inverse_bw, speed, boundingbox)
|
|
796
809
|
else:
|
|
810
|
+
# ignore path
|
|
797
811
|
self.body.extend([f"\n; --color_coded: ignore path '{name_id}', color '{stroke_color}'"])
|
|
798
812
|
|
|
799
|
-
|
|
800
|
-
#
|
|
813
|
+
elif inverse_bw:
|
|
814
|
+
# Get steps (offsets) for the lines that make the border
|
|
815
|
+
steps = [0]
|
|
816
|
+
if stroke_width:
|
|
817
|
+
for delta in range(stroke_width):
|
|
818
|
+
if delta:
|
|
819
|
+
steps.append(round(delta * pixel_size, self.precision))
|
|
820
|
+
if not (delta == stroke_width and stroke_width % 2 != 0):
|
|
821
|
+
steps.append(round(-delta * pixel_size, self.precision))
|
|
822
|
+
|
|
823
|
+
# color_coded isn't set: with path color engrave path
|
|
801
824
|
self.body.extend([f"\n; engrave path '{name_id}', color '{stroke_color}'"])
|
|
802
825
|
render_pathwidth(line_chain, steps, inverse_bw, speed, boundingbox)
|
|
803
826
|
else:
|
|
804
|
-
# line stroke isn't set:
|
|
805
|
-
self.body.extend([f"\n; no stroke color:
|
|
806
|
-
render_pathwidth(line_chain, [0], None, None, boundingbox)
|
|
827
|
+
# line stroke isn't set: ignore path
|
|
828
|
+
self.body.extend([f"\n; no stroke color set: ignore path '{name_id}'"])
|
|
829
|
+
#render_pathwidth(line_chain, [0], None, None, boundingbox)
|
|
807
830
|
|
|
808
831
|
# Render svg 'fill' attribute
|
|
809
|
-
if not self.settings["nofill"] and fill_color is not None and boundingbox.get() is not None:
|
|
832
|
+
#if not self.settings["nofill"] and fill_color is not None and boundingbox.get() is not None:
|
|
833
|
+
if not self.settings["nofill"] and fill_color is not None:
|
|
810
834
|
# fill a path
|
|
811
835
|
# this is done in 6 steps:
|
|
812
836
|
# step 1: create two raster images matching the bbox
|
|
@@ -817,6 +841,12 @@ class Compiler:
|
|
|
817
841
|
# step 5: filter stray pixels (to remove noise from the action above)
|
|
818
842
|
# step 6: generate gcode from image_fill (by execution function image2gcode)
|
|
819
843
|
|
|
844
|
+
# update boundingbox for this 'name_id'
|
|
845
|
+
for line_chain in path_curves[name_id]:
|
|
846
|
+
for line in line_chain:
|
|
847
|
+
boundingbox.update(line.start)
|
|
848
|
+
boundingbox.update(line.end)
|
|
849
|
+
|
|
820
850
|
# get bounding box info from the path border
|
|
821
851
|
lowerleft = boundingbox.get()[0]
|
|
822
852
|
upperright = boundingbox.get()[1]
|
|
@@ -834,8 +864,8 @@ class Compiler:
|
|
|
834
864
|
|
|
835
865
|
# step 1: create two raster images matching the bbox
|
|
836
866
|
# init
|
|
837
|
-
image_mark = np.full([img_height +
|
|
838
|
-
image_fill = np.full([img_height +
|
|
867
|
+
image_mark = np.full([img_height + 4, img_width + scan_error + 2], 255, dtype=np.uint8)
|
|
868
|
+
image_fill = np.full([img_height + 4, img_width + scan_error + 2], 0, dtype=np.uint8)
|
|
839
869
|
|
|
840
870
|
# step 2: add marker lines just inside the line chains of the path
|
|
841
871
|
# - determine the inside of the line chain
|
|
@@ -852,7 +882,7 @@ class Compiler:
|
|
|
852
882
|
# delta line chain is inside or outside the base line chain, but when we compare
|
|
853
883
|
# the bbox sizes we know.
|
|
854
884
|
# Note that this method can be used to determine if a line chain is drawn clockwise
|
|
855
|
-
# or anti-clockwise because a
|
|
885
|
+
# or anti-clockwise because a positive delta offset should be 'outside' the line chain
|
|
856
886
|
# in this case (depending on the definition/calculation of the delta function).
|
|
857
887
|
# we can use this to implement the other svg fill rule: 'nonzero'.
|
|
858
888
|
bbox = Boundingbox()
|
|
@@ -154,22 +154,22 @@ class Gcode(Interface):
|
|
|
154
154
|
|
|
155
155
|
return command + ''
|
|
156
156
|
|
|
157
|
-
def laser_off(self):
|
|
157
|
+
def laser_off(self, fan_off = True):
|
|
158
158
|
self._laser_mode = 'M5'
|
|
159
159
|
self._laser_mode_changed = True
|
|
160
|
-
new_mode = "M5" + ("\nM9" if self._machine_params['fan'] else '') # laser off, (fan off when available)
|
|
160
|
+
new_mode = "M5" + ("\nM9" if self._machine_params['fan'] and fan_off else '') # laser off, (fan off when available)
|
|
161
161
|
return f"{new_mode}"
|
|
162
162
|
|
|
163
|
-
def set_laser_power(self, power):
|
|
163
|
+
def set_laser_power(self, power, fan_on = True):
|
|
164
164
|
print("laser power!")
|
|
165
165
|
if power < 0 or power > 1:
|
|
166
166
|
raise ValueError(f"{power} is out of bounds. Laser power must be given between 0 and 1. "
|
|
167
167
|
f"The interface will scale it correctly.")
|
|
168
168
|
|
|
169
169
|
# set power for next linear move
|
|
170
|
-
return self.set_laser_power_value(int(linear_map(self._machine_params['minimum_laser_power'], self._machine_params['maximum_laser_power'], power)))
|
|
170
|
+
return self.set_laser_power_value(int(linear_map(self._machine_params['minimum_laser_power'], self._machine_params['maximum_laser_power'], power)), fan_on)
|
|
171
171
|
|
|
172
|
-
def set_laser_power_value(self, machine_value) -> str:
|
|
172
|
+
def set_laser_power_value(self, machine_value, fan_on = True) -> str:
|
|
173
173
|
"""
|
|
174
174
|
Set laser power directly - in target machine values - not as a fraction.
|
|
175
175
|
"""
|
|
@@ -177,10 +177,10 @@ class Gcode(Interface):
|
|
|
177
177
|
self._next_laser_power = machine_value
|
|
178
178
|
|
|
179
179
|
# (fan on when available), laser_on
|
|
180
|
-
new_mode = ("\nM8" if self._machine_params['fan'] else '') + ("\n" + self._laser_mode if self._laser_mode_changed else '')
|
|
180
|
+
new_mode = ("\nM8" if self._machine_params['fan'] and fan_on else '') + ("\n" + self._laser_mode if self._laser_mode_changed else '')
|
|
181
181
|
self._laser_mode_changed = False
|
|
182
182
|
# return laser mode (M3 constant laser power or M4 dynamic laser power) when laser mode changed
|
|
183
|
-
return f";
|
|
183
|
+
return f"; F{self._next_speed} {self._unit}/min, power S{machine_value}{new_mode}"
|
|
184
184
|
|
|
185
185
|
def set_laser_mode(self, mode):
|
|
186
186
|
# set constant/dynamic laser power mode
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|