meerk40t 0.9.7030__py2.py3-none-any.whl → 0.9.7040__py2.py3-none-any.whl

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.
Files changed (79) hide show
  1. meerk40t/balormk/clone_loader.py +3 -2
  2. meerk40t/balormk/controller.py +28 -11
  3. meerk40t/balormk/cylindermod.py +1 -0
  4. meerk40t/balormk/device.py +13 -9
  5. meerk40t/balormk/driver.py +9 -2
  6. meerk40t/balormk/galvo_commands.py +3 -1
  7. meerk40t/balormk/gui/gui.py +6 -0
  8. meerk40t/balormk/livelightjob.py +338 -321
  9. meerk40t/balormk/mock_connection.py +4 -3
  10. meerk40t/balormk/usb_connection.py +11 -2
  11. meerk40t/camera/camera.py +19 -14
  12. meerk40t/camera/gui/camerapanel.py +6 -0
  13. meerk40t/core/cutplan.py +109 -51
  14. meerk40t/core/elements/element_treeops.py +435 -140
  15. meerk40t/core/elements/elements.py +100 -9
  16. meerk40t/core/elements/shapes.py +259 -39
  17. meerk40t/core/elements/tree_commands.py +10 -5
  18. meerk40t/core/node/elem_ellipse.py +18 -8
  19. meerk40t/core/node/elem_image.py +51 -19
  20. meerk40t/core/node/elem_line.py +18 -8
  21. meerk40t/core/node/elem_path.py +18 -8
  22. meerk40t/core/node/elem_point.py +10 -4
  23. meerk40t/core/node/elem_polyline.py +19 -11
  24. meerk40t/core/node/elem_rect.py +18 -8
  25. meerk40t/core/node/elem_text.py +11 -5
  26. meerk40t/core/node/filenode.py +2 -8
  27. meerk40t/core/node/groupnode.py +11 -11
  28. meerk40t/core/node/image_processed.py +11 -5
  29. meerk40t/core/node/image_raster.py +11 -5
  30. meerk40t/core/node/node.py +64 -16
  31. meerk40t/core/node/refnode.py +2 -1
  32. meerk40t/core/svg_io.py +91 -34
  33. meerk40t/device/dummydevice.py +7 -1
  34. meerk40t/extra/vtracer.py +222 -0
  35. meerk40t/grbl/device.py +81 -8
  36. meerk40t/gui/about.py +20 -0
  37. meerk40t/gui/devicepanel.py +20 -16
  38. meerk40t/gui/gui_mixins.py +4 -0
  39. meerk40t/gui/icons.py +330 -253
  40. meerk40t/gui/laserpanel.py +8 -3
  41. meerk40t/gui/laserrender.py +41 -21
  42. meerk40t/gui/magnetoptions.py +158 -65
  43. meerk40t/gui/materialtest.py +229 -39
  44. meerk40t/gui/navigationpanels.py +229 -24
  45. meerk40t/gui/propertypanels/hatchproperty.py +2 -0
  46. meerk40t/gui/propertypanels/imageproperty.py +160 -106
  47. meerk40t/gui/ribbon.py +6 -1
  48. meerk40t/gui/scenewidgets/gridwidget.py +29 -32
  49. meerk40t/gui/scenewidgets/rectselectwidget.py +190 -192
  50. meerk40t/gui/simulation.py +75 -77
  51. meerk40t/gui/statusbarwidgets/defaultoperations.py +84 -48
  52. meerk40t/gui/statusbarwidgets/infowidget.py +2 -2
  53. meerk40t/gui/tips.py +15 -1
  54. meerk40t/gui/toolwidgets/toolpointmove.py +3 -1
  55. meerk40t/gui/wxmmain.py +242 -114
  56. meerk40t/gui/wxmscene.py +107 -24
  57. meerk40t/gui/wxmtree.py +4 -2
  58. meerk40t/gui/wxutils.py +60 -15
  59. meerk40t/image/imagetools.py +129 -65
  60. meerk40t/internal_plugins.py +4 -0
  61. meerk40t/kernel/kernel.py +39 -18
  62. meerk40t/kernel/settings.py +28 -9
  63. meerk40t/lihuiyu/device.py +24 -12
  64. meerk40t/main.py +1 -1
  65. meerk40t/moshi/device.py +20 -6
  66. meerk40t/network/console_server.py +22 -6
  67. meerk40t/newly/device.py +10 -3
  68. meerk40t/newly/gui/gui.py +10 -0
  69. meerk40t/ruida/device.py +22 -2
  70. meerk40t/ruida/loader.py +6 -3
  71. meerk40t/tools/geomstr.py +193 -125
  72. meerk40t/tools/rasterplotter.py +179 -93
  73. {meerk40t-0.9.7030.dist-info → meerk40t-0.9.7040.dist-info}/METADATA +1 -1
  74. {meerk40t-0.9.7030.dist-info → meerk40t-0.9.7040.dist-info}/RECORD +79 -78
  75. {meerk40t-0.9.7030.dist-info → meerk40t-0.9.7040.dist-info}/LICENSE +0 -0
  76. {meerk40t-0.9.7030.dist-info → meerk40t-0.9.7040.dist-info}/WHEEL +0 -0
  77. {meerk40t-0.9.7030.dist-info → meerk40t-0.9.7040.dist-info}/entry_points.txt +0 -0
  78. {meerk40t-0.9.7030.dist-info → meerk40t-0.9.7040.dist-info}/top_level.txt +0 -0
  79. {meerk40t-0.9.7030.dist-info → meerk40t-0.9.7040.dist-info}/zip-safe +0 -0
@@ -18,19 +18,21 @@ The rasters can either be BIDIRECTIONAL or UNIDIRECTIONAL meaning they raster on
18
18
  or only on forward swing.
19
19
  """
20
20
 
21
- import numpy as np
22
- from math import sqrt
21
+ from math import isinf, sqrt
23
22
  from time import perf_counter, sleep
23
+
24
+ import numpy as np
25
+
24
26
  from meerk40t.constants import (
25
- RASTER_T2B,
26
27
  RASTER_B2T,
27
- RASTER_R2L,
28
- RASTER_L2R,
29
- RASTER_HATCH,
28
+ RASTER_CROSSOVER,
30
29
  RASTER_GREEDY_H,
31
30
  RASTER_GREEDY_V,
32
- RASTER_CROSSOVER,
31
+ RASTER_HATCH,
32
+ RASTER_L2R,
33
+ RASTER_R2L,
33
34
  RASTER_SPIRAL,
35
+ RASTER_T2B,
34
36
  )
35
37
 
36
38
 
@@ -90,7 +92,7 @@ class RasterPlotter:
90
92
 
91
93
  if special is None:
92
94
  special = {}
93
- self.debug_level = 0 # 0 Nothing, 1 file creation, 2 file + summary, 3 file + summary + details
95
+ self.debug_level = 0 # 0 Nothing, 1 file creation, 2 file + summary, 3 file + summary + details
94
96
  self.data = data
95
97
  self.width = width
96
98
  self.height = height
@@ -98,16 +100,18 @@ class RasterPlotter:
98
100
  self._cache = None
99
101
  parameters = {
100
102
  # Provide an override for the minimumx / minimumy / horizontal / bidirectional
101
- RASTER_T2B: (None, True, True, None), # top to bottom
102
- RASTER_B2T: (None, False, True, None), # bottom to top
103
- RASTER_R2L: (False, None, False, None), # right to left
104
- RASTER_L2R: (True, None, False, None), # left to right
105
- RASTER_HATCH: (None, None, None, None), # crossraster (one of the two)
106
- RASTER_GREEDY_H: (None, None, None, True), # greedy neighbour horizontal
107
- RASTER_GREEDY_V: (None, None, None, True), # greedy neighbour
108
- RASTER_CROSSOVER: (None, None, None, True), # true crossover
103
+ RASTER_T2B: (None, True, True, None), # top to bottom
104
+ RASTER_B2T: (None, False, True, None), # bottom to top
105
+ RASTER_R2L: (False, None, False, None), # right to left
106
+ RASTER_L2R: (True, None, False, None), # left to right
107
+ RASTER_HATCH: (None, None, None, None), # crossraster (one of the two)
108
+ RASTER_GREEDY_H: (None, None, None, True), # greedy neighbour horizontal
109
+ RASTER_GREEDY_V: (None, None, None, True), # greedy neighbour
110
+ RASTER_CROSSOVER: (None, None, None, True), # true crossover
109
111
  }
110
- def_x, def_y, def_hor, def_bidir = parameters.get(direction, (None, None, None, None))
112
+ def_x, def_y, def_hor, def_bidir = parameters.get(
113
+ direction, (None, None, None, None)
114
+ )
111
115
  self.start_minimum_x = start_minimum_x if def_x is None else def_x
112
116
  self.start_minimum_y = start_minimum_y if def_y is None else def_y
113
117
  self.horizontal = horizontal if def_hor is None else def_hor
@@ -120,7 +124,7 @@ class RasterPlotter:
120
124
  # and calculate the overlap in pixels to the left / to the right
121
125
  self.overlap = int(laserspot / sqrt(2) / 2)
122
126
  # self.overlap = 1
123
- self.special = dict(special) # Copy it so it wont be changed
127
+ self.special = dict(special) # Copy it so it wont be changed
124
128
  if horizontal:
125
129
  self.overscan = round(overscan / float(step_x))
126
130
  else:
@@ -150,11 +154,13 @@ class RasterPlotter:
150
154
  if 0 <= self.direction < len(methods):
151
155
  s_meth = f"Rasterplotter ({self.width}x{self.height}): {methods[self.direction]} ({self.direction})"
152
156
  else:
153
- s_meth = f"Rasterplotter ({self.width}x{self.height}): Unknown {self.direction}"
154
- s_direc = 'Bidirectional' if self.bidirectional else 'Unidirectional'
155
- s_axis = 'horizontal' if self.horizontal else 'vertical'
156
- s_ystart = 'top' if self.start_minimum_y else 'bottom'
157
- s_xstart = 'left' if self.start_minimum_x else 'right'
157
+ s_meth = (
158
+ f"Rasterplotter ({self.width}x{self.height}): Unknown {self.direction}"
159
+ )
160
+ s_direc = "Bidirectional" if self.bidirectional else "Unidirectional"
161
+ s_axis = "horizontal" if self.horizontal else "vertical"
162
+ s_ystart = "top" if self.start_minimum_y else "bottom"
163
+ s_xstart = "left" if self.start_minimum_x else "right"
158
164
  return f"{s_meth}, {s_direc} {s_axis} plot starting at {s_ystart}-{s_xstart}"
159
165
 
160
166
  def reset(self):
@@ -434,7 +440,7 @@ class RasterPlotter:
434
440
  Returns the initial position for this within the scene. Taking into account start corner, and step size.
435
441
  @return: initial position within scene. The first plot location.
436
442
  """
437
- if self.initial_x is None: # image is blank.
443
+ if self.initial_x is None or isinf(self.initial_x): # image is blank.
438
444
  if self.use_integers:
439
445
  return int(round(self.offset_x)), int(round(self.offset_y))
440
446
  else:
@@ -518,15 +524,20 @@ class RasterPlotter:
518
524
  s_meth = f"Method: {m} ({self.direction})"
519
525
  except IndexError:
520
526
  s_meth = f"Method: Unknown {self.direction}"
521
- print (s_meth)
527
+ print(s_meth)
522
528
  data = list(self._plot_pixels())
523
529
  from platform import system
530
+
524
531
  defaultdir = "c:\\temp\\" if system() == "Windows" else ""
525
532
  has_duplicates = 0
526
533
  tstamp = int(perf_counter() * 100)
527
534
  with open(f"{defaultdir}plot_{tstamp}.txt", mode="w") as f:
528
- f.write(f"0.9.7\n{s_meth}\n{'Bidirectional' if self.bidirectional else 'Unidirectional'} {'horizontal' if self.horizontal else 'vertical'} plot starting at {'top' if self.start_minimum_y else 'bottom'}-{'left' if self.start_minimum_x else 'right'}\n")
529
- f.write(f"Overscan: {self.overscan:.2f}, Stepx={step_x:.2f}, Stepy={step_y:.2f}\n")
535
+ f.write(
536
+ f"0.9.7\n{s_meth}\n{'Bidirectional' if self.bidirectional else 'Unidirectional'} {'horizontal' if self.horizontal else 'vertical'} plot starting at {'top' if self.start_minimum_y else 'bottom'}-{'left' if self.start_minimum_x else 'right'}\n"
537
+ )
538
+ f.write(
539
+ f"Overscan: {self.overscan:.2f}, Stepx={step_x:.2f}, Stepy={step_y:.2f}\n"
540
+ )
530
541
  f.write(f"Image dimensions: {self.width}x{self.height}\n")
531
542
  f.write(f"Startpoint: {self.initial_x}, {self.initial_y}\n")
532
543
  f.write(f"Overlapping pixels to any side: {self.overlap}\n")
@@ -534,7 +545,9 @@ class RasterPlotter:
534
545
  f.write(f"Special instructions:\n")
535
546
  for key, value in self.special.items():
536
547
  f.write(f" {key} = {value}\n")
537
- f.write("----------------------------------------------------------------------\n")
548
+ f.write(
549
+ "----------------------------------------------------------------------\n"
550
+ )
538
551
  test_dict = {}
539
552
  lastx = self.initial_x
540
553
  lasty = self.initial_y
@@ -543,32 +556,48 @@ class RasterPlotter:
543
556
  if lastx is not None:
544
557
  dx = x - lastx
545
558
  dy = y - lasty
546
- if dx != 0 and dy != 0: # and abs(dx) != abs(dy):
547
- f.write (f"You f**ed up! No zigzag movement from line {lineno - 1} to {lineno}: {lastx}, {lasty} -> {x}, {y}\n")
548
- print (f"You f**ed up! No zigzag movement from line {lineno - 1} to {lineno}: {lastx}, {lasty} -> {x}, {y}")
559
+ if dx != 0 and dy != 0: # and abs(dx) != abs(dy):
560
+ f.write(
561
+ f"You f**ed up! No zigzag movement from line {lineno - 1} to {lineno}: {lastx}, {lasty} -> {x}, {y}\n"
562
+ )
563
+ print(
564
+ f"You f**ed up! No zigzag movement from line {lineno - 1} to {lineno}: {lastx}, {lasty} -> {x}, {y}"
565
+ )
549
566
  failed = True
550
567
  lastx = x
551
568
  lasty = y
552
569
  if not failed:
553
570
  f.write("Good news, no zig-zag movements identified!\n")
554
- f.write("----------------------------------------------------------------------\n")
571
+ f.write(
572
+ "----------------------------------------------------------------------\n"
573
+ )
555
574
  for lineno, (x, y, on) in enumerate(data, start=1):
556
575
  if x is None or y is None:
557
576
  continue
558
577
  key = f"{x} - {y}"
559
578
  if key in test_dict:
560
- f.write (f"Duplicate coordinates in list at ({x}, {y})! 1st: #{test_dict[key][0]}, on={test_dict[key][1]}, 2nd: #{lineno}, on={on}\n")
579
+ f.write(
580
+ f"Duplicate coordinates in list at ({x}, {y})! 1st: #{test_dict[key][0]}, on={test_dict[key][1]}, 2nd: #{lineno}, on={on}\n"
581
+ )
561
582
  has_duplicates += 1
562
583
  else:
563
584
  test_dict[key] = (lineno, on)
564
585
  if has_duplicates:
565
- f.write("----------------------------------------------------------------------\n")
586
+ f.write(
587
+ "----------------------------------------------------------------------\n"
588
+ )
566
589
  for lineno, (x, y, on) in enumerate(data, start=1):
567
590
  f.write(f"{lineno}: {x}, {y}, {on}\n")
568
591
  if has_duplicates:
569
- print(f"Attention: the generated plot has {has_duplicates} duplicate coordinate values!")
570
- print(f"{'Bidirectional' if self.bidirectional else 'Unidirectional'} {'horizontal' if self.horizontal else 'vertical'} plot starting at {'top' if self.start_minimum_y else 'bottom'}-{'left' if self.start_minimum_x else 'right'}")
571
- print(f"Overscan: {self.overscan:.2f}, Stepx={step_x:.2f}, Stepy={step_y:.2f}")
592
+ print(
593
+ f"Attention: the generated plot has {has_duplicates} duplicate coordinate values!"
594
+ )
595
+ print(
596
+ f"{'Bidirectional' if self.bidirectional else 'Unidirectional'} {'horizontal' if self.horizontal else 'vertical'} plot starting at {'top' if self.start_minimum_y else 'bottom'}-{'left' if self.start_minimum_x else 'right'}"
597
+ )
598
+ print(
599
+ f"Overscan: {self.overscan:.2f}, Stepx={step_x:.2f}, Stepy={step_y:.2f}"
600
+ )
572
601
  print(f"Image dimensions: {self.width}x{self.height}")
573
602
  else:
574
603
  data = list(self._plot_pixels())
@@ -585,8 +614,22 @@ class RasterPlotter:
585
614
  else:
586
615
  nx = int(round(offset_x + step_x * x))
587
616
  ny = int(round(offset_y + y * step_y))
588
- self._distance_burn += 0 if on == 0 else sqrt( (nx - last_x) * (nx-last_x) + (ny - last_y) * (ny - last_y) )
589
- self._distance_travel += 0 if on != 0 else sqrt( (nx - last_x) * (nx-last_x) + (ny - last_y) * (ny - last_y) )
617
+ self._distance_burn += (
618
+ 0
619
+ if on == 0
620
+ else sqrt(
621
+ (nx - last_x) * (nx - last_x)
622
+ + (ny - last_y) * (ny - last_y)
623
+ )
624
+ )
625
+ self._distance_travel += (
626
+ 0
627
+ if on != 0
628
+ else sqrt(
629
+ (nx - last_x) * (nx - last_x)
630
+ + (ny - last_y) * (ny - last_y)
631
+ )
632
+ )
590
633
  yield nx, ny, on
591
634
  last_x = nx
592
635
  last_y = ny
@@ -598,8 +641,22 @@ class RasterPlotter:
598
641
  else:
599
642
  nx = round(offset_x + step_x * x)
600
643
  ny = round(offset_y + y * step_y)
601
- self._distance_burn += 0 if on == 0 else sqrt( (nx - last_x) * (nx-last_x) + (ny - last_y) * (ny - last_y) )
602
- self._distance_travel += 0 if on != 0 else sqrt( (nx - last_x) * (nx-last_x) + (ny - last_y) * (ny - last_y) )
644
+ self._distance_burn += (
645
+ 0
646
+ if on == 0
647
+ else sqrt(
648
+ (nx - last_x) * (nx - last_x)
649
+ + (ny - last_y) * (ny - last_y)
650
+ )
651
+ )
652
+ self._distance_travel += (
653
+ 0
654
+ if on != 0
655
+ else sqrt(
656
+ (nx - last_x) * (nx - last_x)
657
+ + (ny - last_y) * (ny - last_y)
658
+ )
659
+ )
603
660
  yield offset_x + step_x * x, offset_y + y * step_y, on
604
661
  last_x = nx
605
662
  last_y = ny
@@ -632,12 +689,12 @@ class RasterPlotter:
632
689
  return
633
690
  BLANK = 255
634
691
  for y in range(self.height):
635
- msg:str = f"{y:3d}: "
692
+ msg: str = f"{y:3d}: "
636
693
  for x in range(self.width):
637
694
  msg += "." if self.data[x, y] == BLANK else "X"
638
- print (msg)
695
+ print(msg)
639
696
 
640
- def _get_pixel_chains(self, xy:int, is_x : bool) -> list:
697
+ def _get_pixel_chains(self, xy: int, is_x: bool) -> list:
641
698
  last_pixel = None
642
699
  segments = []
643
700
  upper = self.width if is_x else self.height
@@ -648,11 +705,11 @@ class RasterPlotter:
648
705
  if on == last_pixel:
649
706
  segments[-1][1] = idx
650
707
  else:
651
- segments.append ([idx, idx, on])
708
+ segments.append([idx, idx, on])
652
709
  last_pixel = on
653
710
  return segments
654
711
 
655
- def _consume_pixel_chains(self, segments:list, xy:int, is_x : bool):
712
+ def _consume_pixel_chains(self, segments: list, xy: int, is_x: bool):
656
713
  BLANK = 255
657
714
  # for x in range(5):
658
715
  # msg1 = f"{x}: "
@@ -727,7 +784,11 @@ class RasterPlotter:
727
784
  # We consider as well the overscan value
728
785
  overscan_top = 0 if dy >= 0 else self.overscan
729
786
  overscan_bottom = 0 if dy <= 0 else self.overscan
730
- if not first and (segments[0][0] - overscan_top <= last_y <= segments[-1][1] + overscan_bottom):
787
+ if not first and (
788
+ segments[0][0] - overscan_top
789
+ <= last_y
790
+ <= segments[-1][1] + overscan_bottom
791
+ ):
731
792
  # inside the chain!
732
793
  # So lets move a bit to the side
733
794
  if dy > 0:
@@ -814,7 +875,11 @@ class RasterPlotter:
814
875
  # We consider as well the overscan value
815
876
  overscan_left = 0 if dx >= 0 else self.overscan
816
877
  overscan_right = 0 if dx <= 0 else self.overscan
817
- if not first and (segments[0][0] - overscan_left <= last_x <= segments[-1][1] + overscan_right):
878
+ if not first and (
879
+ segments[0][0] - overscan_left
880
+ <= last_x
881
+ <= segments[-1][1] + overscan_right
882
+ ):
818
883
  # inside the chain!
819
884
  # So lets move a bit to the side
820
885
  if dx > 0:
@@ -1021,12 +1086,14 @@ class RasterPlotter:
1021
1086
  """
1022
1087
 
1023
1088
  def walk_segments(segments, horizontal=True, xy_penalty=1, width=1, height=1):
1024
- n:int = len(segments)
1089
+ n: int = len(segments)
1025
1090
  visited = np.zeros(n, dtype=bool)
1026
1091
  path = []
1027
1092
  window_size = 10
1028
1093
  current_point = np.array(segments[0][0], dtype=float)
1029
- segment_points = np.array([point for segment in segments for point in segment], dtype=float)
1094
+ segment_points = np.array(
1095
+ [point for segment in segments for point in segment], dtype=float
1096
+ )
1030
1097
  mask = ~visited.repeat(2)
1031
1098
  while len(path) < n:
1032
1099
  # Find the range of segments within the x- and y-window
@@ -1035,17 +1102,19 @@ class RasterPlotter:
1035
1102
  y_min = current_point[1] - window_size
1036
1103
  y_max = current_point[1] + window_size
1037
1104
  unvisited_indices = np.where(
1038
- (segment_points[:, 0] >= x_min) &
1039
- (segment_points[:, 0] <= x_max) &
1040
- (segment_points[:, 1] >= y_min) &
1041
- (segment_points[:, 1] <= y_max) &
1042
- mask
1105
+ (segment_points[:, 0] >= x_min)
1106
+ & (segment_points[:, 0] <= x_max)
1107
+ & (segment_points[:, 1] >= y_min)
1108
+ & (segment_points[:, 1] <= y_max)
1109
+ & mask
1043
1110
  )[0]
1044
1111
  if len(unvisited_indices) == 0:
1045
1112
  # If no segments are within the window, expand the window
1046
1113
  window_size *= 2
1047
1114
  # print (f"Did not find points: now window: {window_size}")
1048
- if window_size <= 2* height or window_size <= 2 * width: # Safety belt
1115
+ if (
1116
+ window_size <= 2 * height or window_size <= 2 * width
1117
+ ): # Safety belt
1049
1118
  continue
1050
1119
 
1051
1120
  unvisited_points = segment_points[unvisited_indices]
@@ -1053,11 +1122,11 @@ class RasterPlotter:
1053
1122
  # distances = distance_matrix(unvisited_points, current_point, y_penalty)
1054
1123
  diff = unvisited_points - current_point
1055
1124
  if horizontal:
1056
- diff[:, 1] *= xy_penalty # Apply penalty to y-distances
1125
+ diff[:, 1] *= xy_penalty # Apply penalty to y-distances
1057
1126
  else:
1058
- diff[:, 0] *= xy_penalty # Apply penalty to x-distances
1127
+ diff[:, 0] *= xy_penalty # Apply penalty to x-distances
1059
1128
 
1060
- distances = np.sum(diff ** 2, axis=1) # Return squared distances
1129
+ distances = np.sum(diff**2, axis=1) # Return squared distances
1061
1130
 
1062
1131
  min_distance_idx = np.argmin(distances)
1063
1132
  next_segment = unvisited_indices[min_distance_idx] // 2
@@ -1068,12 +1137,16 @@ class RasterPlotter:
1068
1137
  mask[2 * next_segment] = False
1069
1138
  mask[2 * next_segment + 1] = False
1070
1139
  if min_distance_idx % 2 == 0:
1071
- path.append((next_segment, 'end'))
1072
- current_point = segment_points[next_segment * 2 + 1] # Move to the other endpoint
1140
+ path.append((next_segment, "end"))
1141
+ current_point = segment_points[
1142
+ next_segment * 2 + 1
1143
+ ] # Move to the other endpoint
1073
1144
  else:
1074
- path.append((next_segment, 'start'))
1075
- current_point = segment_points[next_segment * 2] # Move to the other endpoint
1076
- window_size = 10 # Reset window size
1145
+ path.append((next_segment, "start"))
1146
+ current_point = segment_points[
1147
+ next_segment * 2
1148
+ ] # Move to the other endpoint
1149
+ window_size = 10 # Reset window size
1077
1150
 
1078
1151
  return path
1079
1152
 
@@ -1093,14 +1166,16 @@ class RasterPlotter:
1093
1166
  line_parts = []
1094
1167
  on_parts = []
1095
1168
  if self.debug_level > 2:
1096
- print (f"{'horizontal' if horizontal else 'Vertical'} for {self.width}x{self.height} image. {'y' if horizontal else 'x'} from {lower} to {upper}")
1169
+ print(
1170
+ f"{'horizontal' if horizontal else 'Vertical'} for {self.width}x{self.height} image. {'y' if horizontal else 'x'} from {lower} to {upper}"
1171
+ )
1097
1172
  if horizontal:
1098
1173
  while lower <= y <= upper:
1099
1174
  segments = self._get_pixel_chains(y, True)
1100
1175
  self._consume_pixel_chains(segments, y, True)
1101
1176
  for seg in segments:
1102
1177
  # Append (xstart, y), (xend, y), on
1103
- line_parts.append( ( (seg[0], y), (seg[1], y) ) )
1178
+ line_parts.append(((seg[0], y), (seg[1], y)))
1104
1179
  on_parts.append(seg[2])
1105
1180
  y += dy
1106
1181
  else:
@@ -1109,14 +1184,20 @@ class RasterPlotter:
1109
1184
  self._consume_pixel_chains(segments, x, False)
1110
1185
  for seg in segments:
1111
1186
  # Append (xstart, y), (xend, y), on
1112
- line_parts.append( ( (x, seg[0]), (x, seg[1]) ) )
1187
+ line_parts.append(((x, seg[0]), (x, seg[1])))
1113
1188
  on_parts.append(seg[2])
1114
1189
  x += dx
1115
1190
  if self.debug_level > 2:
1116
- print (f"Created {len(line_parts)} segments")
1191
+ print(f"Created {len(line_parts)} segments")
1117
1192
  t1 = perf_counter()
1118
1193
  penalty = 3 if self.special.get("gantry", False) else 1
1119
- path = walk_segments(line_parts, horizontal=horizontal, xy_penalty=penalty, width=self.width, height=self.height)
1194
+ path = walk_segments(
1195
+ line_parts,
1196
+ horizontal=horizontal,
1197
+ xy_penalty=penalty,
1198
+ width=self.width,
1199
+ height=self.height,
1200
+ )
1120
1201
  # print("Order of segments:", path)
1121
1202
  t2 = perf_counter()
1122
1203
  if horizontal:
@@ -1171,14 +1252,16 @@ class RasterPlotter:
1171
1252
  last_y = ey
1172
1253
  t3 = perf_counter()
1173
1254
  if self.debug_level > 1:
1174
- print (f"Overall time for {'horizontal' if horizontal else 'vertical'} consumption: {t3-t0:.2f}s - created: {len(line_parts)} segments")
1175
- print (f"Computation: {t2-t0:.2f}s - Chain creation:{t1 - t0:.2f}s, Walk: {t2 - t1:.2f}s")
1255
+ print(
1256
+ f"Overall time for {'horizontal' if horizontal else 'vertical'} consumption: {t3-t0:.2f}s - created: {len(line_parts)} segments"
1257
+ )
1258
+ print(
1259
+ f"Computation: {t2-t0:.2f}s - Chain creation:{t1 - t0:.2f}s, Walk: {t2 - t1:.2f}s"
1260
+ )
1176
1261
  self.final_x = last_x
1177
1262
  self.final_y = last_y
1178
1263
 
1179
1264
  def _plot_spiral(self):
1180
-
1181
-
1182
1265
  rows = self.height
1183
1266
  cols = self.width
1184
1267
  center_row, center_col = rows // 2, cols // 2
@@ -1223,7 +1306,7 @@ class RasterPlotter:
1223
1306
  if on == last_pixel and len(segments):
1224
1307
  segments[-1][1] = (col, row)
1225
1308
  else:
1226
- segments.append ([(col, row), (col, row), on])
1309
+ segments.append([(col, row), (col, row), on])
1227
1310
 
1228
1311
  last_pixel = on
1229
1312
  count += 1
@@ -1255,7 +1338,7 @@ class RasterPlotter:
1255
1338
  sy = min(start_y, end_y)
1256
1339
  ey = max(start_y, end_y)
1257
1340
 
1258
- if direction_index in (0, 2): # horizontal
1341
+ if direction_index in (0, 2): # horizontal
1259
1342
  for y_idx in range(-self.overlap, self.overlap + 1):
1260
1343
  ny = sy + y_idx
1261
1344
  for nx in range(sx, ex + 1):
@@ -1268,11 +1351,9 @@ class RasterPlotter:
1268
1351
  if 0 <= nx < self.width and 0 <= ny < self.height:
1269
1352
  self.data[nx, ny] = BLANK
1270
1353
 
1271
-
1272
1354
  direction_index = (direction_index + 1) % 4
1273
1355
  steps += 1
1274
1356
 
1275
-
1276
1357
  def _plot_crossover(self):
1277
1358
  """
1278
1359
  This algorithm scans through the image looking for the row or the column with the most pixels.
@@ -1289,8 +1370,8 @@ class RasterPlotter:
1289
1370
  Yields:
1290
1371
  list of tuples with (x, y, on)
1291
1372
  """
1292
- ROW=0
1293
- COL=1
1373
+ ROW = 0
1374
+ COL = 1
1294
1375
 
1295
1376
  def process_image(image):
1296
1377
  # We will modify the image to keep track of deleted rows and columns
@@ -1373,28 +1454,30 @@ class RasterPlotter:
1373
1454
  # msg = f"{msg}{'X' if on else '.'}"
1374
1455
  if on:
1375
1456
  if not covered_col[idx]:
1376
- covered_col[idx] = None # needs recalc
1457
+ covered_col[idx] = None # needs recalc
1377
1458
  if on == last_pixel:
1378
1459
  segments[-1][1] = idx
1379
1460
  else:
1380
- segments.append ([idx, idx, on])
1461
+ segments.append([idx, idx, on])
1381
1462
  last_pixel = on
1382
- results.append((COL, rowidx, segments)) # Intentionally so, as the numpy array has x and y exchanged
1463
+ results.append(
1464
+ (COL, rowidx, segments)
1465
+ ) # Intentionally so, as the numpy array has x and y exchanged
1383
1466
  # print (f"Col #{rowidx}: {msg} -> {segments}")
1384
1467
 
1385
1468
  # Clear the column
1386
- image[rowidx,:] = 0
1469
+ image[rowidx, :] = 0
1387
1470
  covered_row[rowidx] = True
1388
1471
  stored_row[rowidx] = 0
1389
1472
  for rc in range(self.overlap):
1390
1473
  r = rowidx - rc
1391
1474
  if 0 <= r < rows:
1392
- image[r,:] = 0
1475
+ image[r, :] = 0
1393
1476
  covered_row[r] = True
1394
1477
  stored_row[r] = 0
1395
1478
  r = rowidx + rc
1396
1479
  if 0 <= r < rows:
1397
- image[r,:] = 0
1480
+ image[r, :] = 0
1398
1481
  covered_row[r] = True
1399
1482
  stored_row[r] = 0
1400
1483
  recalc_col = True
@@ -1407,11 +1490,11 @@ class RasterPlotter:
1407
1490
  # msg = f"{msg}{'X' if on else '.'}"
1408
1491
  if on:
1409
1492
  if not covered_row[idx]:
1410
- covered_row[idx] = None # needs recalc
1493
+ covered_row[idx] = None # needs recalc
1411
1494
  if on == last_pixel:
1412
1495
  segments[-1][1] = idx
1413
1496
  else:
1414
- segments.append ([idx, idx, on])
1497
+ segments.append([idx, idx, on])
1415
1498
  last_pixel = on
1416
1499
  results.append((ROW, colidx, segments))
1417
1500
  # print (f"Row #{colidx}: {msg} -> {segments}")
@@ -1437,7 +1520,7 @@ class RasterPlotter:
1437
1520
  for ridx in range(rows):
1438
1521
  on = image[ridx, cidx]
1439
1522
  msg = f"{msg}{'X' if on else '.'}"
1440
- print (f"{cidx:3d}: {msg}")
1523
+ print(f"{cidx:3d}: {msg}")
1441
1524
 
1442
1525
  return results
1443
1526
 
@@ -1448,7 +1531,7 @@ class RasterPlotter:
1448
1531
  for x in range(self.width):
1449
1532
  for y in range(self.height):
1450
1533
  px = self.px(x, y)
1451
- if px==self.skip_pixel:
1534
+ if px == self.skip_pixel:
1452
1535
  px = 0
1453
1536
  image[x, y] = px
1454
1537
  t1 = perf_counter()
@@ -1528,7 +1611,7 @@ class RasterPlotter:
1528
1611
  if self.bidirectional:
1529
1612
  if mode == ROW:
1530
1613
  dx = -dx
1531
- else: # column
1614
+ else: # column
1532
1615
  dy = -dy
1533
1616
 
1534
1617
  # We need to set the final values so that the rastercut is able to carry on
@@ -1536,8 +1619,11 @@ class RasterPlotter:
1536
1619
  self.final_y = last_y
1537
1620
  t3 = perf_counter()
1538
1621
  if self.debug_level > 1:
1539
- print (f"Overall time for crossover consumption: {t3-t0:.2f}s")
1540
- print (f"Computation: {t2 - t0:.2f}s - Array creation:{t1 - t0:.2f}s, Algorithm: {t2 - t1:.2f}s")
1622
+ print(f"Overall time for crossover consumption: {t3-t0:.2f}s")
1623
+ print(
1624
+ f"Computation: {t2 - t0:.2f}s - Array creation:{t1 - t0:.2f}s, Algorithm: {t2 - t1:.2f}s"
1625
+ )
1626
+
1541
1627
  """
1542
1628
  # Testpattern generation
1543
1629
  def testpattern_generator(self):
@@ -1657,4 +1743,4 @@ class RasterPlotter:
1657
1743
  yield from methods[method]()
1658
1744
  except IndexError:
1659
1745
  print (f"Unknown testgenerator for {self.direction}")
1660
- """
1746
+ """
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: meerk40t
3
- Version: 0.9.7030
3
+ Version: 0.9.7040
4
4
  Summary: MeerK40t LaserCutter Software
5
5
  Home-page: https://github.com/meerk40t/meerk40t
6
6
  Author: Tatarize