meerk40t 0.9.2000__py2.py3-none-any.whl → 0.9.3001__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 (187) hide show
  1. meerk40t/balormk/balor_params.py +1 -43
  2. meerk40t/balormk/controller.py +1 -41
  3. meerk40t/balormk/device.py +16 -22
  4. meerk40t/balormk/driver.py +4 -4
  5. meerk40t/balormk/gui/balorconfig.py +2 -2
  6. meerk40t/balormk/gui/balorcontroller.py +13 -5
  7. meerk40t/balormk/gui/baloroperationproperties.py +0 -46
  8. meerk40t/balormk/gui/gui.py +17 -17
  9. meerk40t/camera/gui/camerapanel.py +18 -11
  10. meerk40t/core/cutcode/rastercut.py +3 -1
  11. meerk40t/core/cutplan.py +145 -14
  12. meerk40t/core/elements/clipboard.py +18 -9
  13. meerk40t/core/elements/element_treeops.py +320 -180
  14. meerk40t/core/elements/element_types.py +7 -2
  15. meerk40t/core/elements/elements.py +53 -27
  16. meerk40t/core/elements/geometry.py +8 -0
  17. meerk40t/core/elements/offset_clpr.py +129 -4
  18. meerk40t/core/elements/offset_mk.py +3 -1
  19. meerk40t/core/elements/shapes.py +28 -25
  20. meerk40t/core/laserjob.py +7 -0
  21. meerk40t/core/node/bootstrap.py +4 -0
  22. meerk40t/core/node/effect_hatch.py +85 -96
  23. meerk40t/core/node/effect_wobble.py +309 -0
  24. meerk40t/core/node/elem_image.py +49 -19
  25. meerk40t/core/node/elem_line.py +60 -0
  26. meerk40t/core/node/elem_rect.py +5 -3
  27. meerk40t/core/node/image_processed.py +766 -0
  28. meerk40t/core/node/image_raster.py +113 -0
  29. meerk40t/core/node/node.py +120 -1
  30. meerk40t/core/node/op_cut.py +2 -8
  31. meerk40t/core/node/op_dots.py +0 -8
  32. meerk40t/core/node/op_engrave.py +2 -18
  33. meerk40t/core/node/op_image.py +22 -35
  34. meerk40t/core/node/op_raster.py +0 -9
  35. meerk40t/core/planner.py +32 -2
  36. meerk40t/core/svg_io.py +699 -461
  37. meerk40t/core/treeop.py +191 -0
  38. meerk40t/core/undos.py +15 -1
  39. meerk40t/core/units.py +14 -4
  40. meerk40t/device/dummydevice.py +3 -2
  41. meerk40t/device/gui/defaultactions.py +43 -55
  42. meerk40t/device/gui/formatterpanel.py +58 -49
  43. meerk40t/device/gui/warningpanel.py +12 -12
  44. meerk40t/device/mixins.py +13 -0
  45. meerk40t/dxf/dxf_io.py +9 -5
  46. meerk40t/extra/ezd.py +28 -26
  47. meerk40t/extra/imageactions.py +300 -308
  48. meerk40t/extra/lbrn.py +19 -2
  49. meerk40t/fill/fills.py +6 -6
  50. meerk40t/fill/patternfill.py +1061 -1061
  51. meerk40t/fill/patterns.py +2 -6
  52. meerk40t/grbl/controller.py +168 -52
  53. meerk40t/grbl/device.py +23 -18
  54. meerk40t/grbl/driver.py +39 -0
  55. meerk40t/grbl/emulator.py +79 -19
  56. meerk40t/grbl/gcodejob.py +10 -0
  57. meerk40t/grbl/gui/grblconfiguration.py +2 -2
  58. meerk40t/grbl/gui/grblcontroller.py +24 -8
  59. meerk40t/grbl/gui/grblhardwareconfig.py +153 -0
  60. meerk40t/grbl/gui/gui.py +17 -14
  61. meerk40t/grbl/mock_connection.py +15 -34
  62. meerk40t/grbl/plugin.py +0 -4
  63. meerk40t/grbl/serial_connection.py +2 -1
  64. meerk40t/gui/about.py +8 -5
  65. meerk40t/gui/alignment.py +10 -6
  66. meerk40t/gui/basicops.py +27 -17
  67. meerk40t/gui/bufferview.py +2 -2
  68. meerk40t/gui/choicepropertypanel.py +101 -13
  69. meerk40t/gui/consolepanel.py +12 -9
  70. meerk40t/gui/devicepanel.py +38 -25
  71. meerk40t/gui/executejob.py +6 -4
  72. meerk40t/gui/help_assets/help_assets.py +13 -10
  73. meerk40t/gui/hersheymanager.py +8 -6
  74. meerk40t/gui/icons.py +1951 -3065
  75. meerk40t/gui/imagesplitter.py +14 -7
  76. meerk40t/gui/keymap.py +3 -3
  77. meerk40t/gui/laserpanel.py +151 -84
  78. meerk40t/gui/laserrender.py +61 -70
  79. meerk40t/gui/lasertoolpanel.py +8 -7
  80. meerk40t/gui/materialtest.py +3 -3
  81. meerk40t/gui/mkdebug.py +254 -1
  82. meerk40t/gui/navigationpanels.py +321 -180
  83. meerk40t/gui/notes.py +3 -3
  84. meerk40t/gui/opassignment.py +12 -12
  85. meerk40t/gui/operation_info.py +13 -13
  86. meerk40t/gui/plugin.py +5 -0
  87. meerk40t/gui/position.py +20 -18
  88. meerk40t/gui/preferences.py +21 -6
  89. meerk40t/gui/propertypanels/attributes.py +70 -22
  90. meerk40t/gui/propertypanels/blobproperty.py +2 -2
  91. meerk40t/gui/propertypanels/consoleproperty.py +2 -2
  92. meerk40t/gui/propertypanels/groupproperties.py +3 -3
  93. meerk40t/gui/propertypanels/hatchproperty.py +11 -18
  94. meerk40t/gui/propertypanels/imageproperty.py +4 -3
  95. meerk40t/gui/propertypanels/opbranchproperties.py +1 -1
  96. meerk40t/gui/propertypanels/pathproperty.py +2 -2
  97. meerk40t/gui/propertypanels/pointproperty.py +2 -2
  98. meerk40t/gui/propertypanels/propertywindow.py +4 -4
  99. meerk40t/gui/propertypanels/textproperty.py +3 -3
  100. meerk40t/gui/propertypanels/wobbleproperty.py +204 -0
  101. meerk40t/gui/ribbon.py +367 -259
  102. meerk40t/gui/scene/scene.py +31 -5
  103. meerk40t/gui/scenewidgets/elementswidget.py +12 -4
  104. meerk40t/gui/scenewidgets/gridwidget.py +2 -2
  105. meerk40t/gui/scenewidgets/laserpathwidget.py +7 -2
  106. meerk40t/gui/scenewidgets/machineoriginwidget.py +6 -2
  107. meerk40t/gui/scenewidgets/relocatewidget.py +1 -1
  108. meerk40t/gui/scenewidgets/reticlewidget.py +9 -0
  109. meerk40t/gui/scenewidgets/selectionwidget.py +12 -7
  110. meerk40t/gui/simpleui.py +95 -8
  111. meerk40t/gui/simulation.py +44 -36
  112. meerk40t/gui/spoolerpanel.py +124 -26
  113. meerk40t/gui/statusbarwidgets/defaultoperations.py +18 -6
  114. meerk40t/gui/statusbarwidgets/infowidget.py +2 -2
  115. meerk40t/gui/statusbarwidgets/opassignwidget.py +12 -12
  116. meerk40t/gui/statusbarwidgets/shapepropwidget.py +45 -18
  117. meerk40t/gui/statusbarwidgets/statusbar.py +11 -4
  118. meerk40t/gui/themes.py +78 -0
  119. meerk40t/gui/toolwidgets/toolcircle.py +2 -1
  120. meerk40t/gui/toolwidgets/toolellipse.py +2 -1
  121. meerk40t/gui/toolwidgets/toolimagecut.py +132 -0
  122. meerk40t/gui/toolwidgets/toolline.py +144 -0
  123. meerk40t/gui/toolwidgets/toolnodeedit.py +72 -145
  124. meerk40t/gui/toolwidgets/toolpoint.py +1 -1
  125. meerk40t/gui/toolwidgets/toolpolygon.py +8 -55
  126. meerk40t/gui/toolwidgets/toolrect.py +2 -1
  127. meerk40t/gui/usbconnect.py +2 -2
  128. meerk40t/gui/utilitywidgets/cyclocycloidwidget.py +2 -2
  129. meerk40t/gui/utilitywidgets/harmonograph.py +7 -7
  130. meerk40t/gui/utilitywidgets/scalewidget.py +1 -1
  131. meerk40t/gui/wordlisteditor.py +33 -18
  132. meerk40t/gui/wxmeerk40t.py +166 -66
  133. meerk40t/gui/wxmmain.py +236 -157
  134. meerk40t/gui/wxmribbon.py +49 -25
  135. meerk40t/gui/wxmscene.py +49 -38
  136. meerk40t/gui/wxmtree.py +216 -85
  137. meerk40t/gui/wxutils.py +62 -4
  138. meerk40t/image/imagetools.py +443 -15
  139. meerk40t/internal_plugins.py +2 -10
  140. meerk40t/kernel/kernel.py +12 -4
  141. meerk40t/lihuiyu/controller.py +7 -7
  142. meerk40t/lihuiyu/device.py +3 -1
  143. meerk40t/lihuiyu/driver.py +3 -0
  144. meerk40t/lihuiyu/gui/gui.py +8 -8
  145. meerk40t/lihuiyu/gui/lhyaccelgui.py +2 -2
  146. meerk40t/lihuiyu/gui/lhycontrollergui.py +73 -27
  147. meerk40t/lihuiyu/gui/lhydrivergui.py +2 -2
  148. meerk40t/lihuiyu/gui/tcpcontroller.py +22 -9
  149. meerk40t/main.py +6 -1
  150. meerk40t/moshi/controller.py +5 -5
  151. meerk40t/moshi/device.py +5 -2
  152. meerk40t/moshi/driver.py +4 -0
  153. meerk40t/moshi/gui/gui.py +8 -8
  154. meerk40t/moshi/gui/moshicontrollergui.py +24 -8
  155. meerk40t/moshi/gui/moshidrivergui.py +2 -2
  156. meerk40t/newly/controller.py +2 -0
  157. meerk40t/newly/device.py +9 -2
  158. meerk40t/newly/driver.py +4 -0
  159. meerk40t/newly/gui/gui.py +16 -17
  160. meerk40t/newly/gui/newlyconfig.py +2 -2
  161. meerk40t/newly/gui/newlycontroller.py +13 -5
  162. meerk40t/rotary/gui/gui.py +2 -2
  163. meerk40t/rotary/gui/rotarysettings.py +2 -2
  164. meerk40t/ruida/device.py +3 -0
  165. meerk40t/ruida/driver.py +4 -0
  166. meerk40t/ruida/gui/gui.py +6 -6
  167. meerk40t/ruida/gui/ruidaconfig.py +2 -2
  168. meerk40t/ruida/gui/ruidacontroller.py +13 -5
  169. meerk40t/svgelements.py +9 -9
  170. meerk40t/tools/geomstr.py +849 -153
  171. meerk40t/tools/kerftest.py +8 -4
  172. meerk40t/tools/livinghinges.py +15 -8
  173. {meerk40t-0.9.2000.dist-info → meerk40t-0.9.3001.dist-info}/METADATA +21 -16
  174. {meerk40t-0.9.2000.dist-info → meerk40t-0.9.3001.dist-info}/RECORD +185 -177
  175. {meerk40t-0.9.2000.dist-info → meerk40t-0.9.3001.dist-info}/entry_points.txt +0 -1
  176. test/test_core_elements.py +8 -24
  177. test/test_file_svg.py +88 -0
  178. test/test_fill.py +9 -9
  179. test/test_geomstr.py +258 -8
  180. test/test_kernel.py +4 -0
  181. test/test_tools_rasterplotter.py +29 -0
  182. meerk40t/extra/embroider.py +0 -56
  183. meerk40t/extra/pathoptimize.py +0 -249
  184. {meerk40t-0.9.2000.dist-info → meerk40t-0.9.3001.dist-info}/LICENSE +0 -0
  185. {meerk40t-0.9.2000.dist-info → meerk40t-0.9.3001.dist-info}/WHEEL +0 -0
  186. {meerk40t-0.9.2000.dist-info → meerk40t-0.9.3001.dist-info}/top_level.txt +0 -0
  187. {meerk40t-0.9.2000.dist-info → meerk40t-0.9.3001.dist-info}/zip-safe +0 -0
@@ -96,7 +96,7 @@ class ImageNode(Node):
96
96
  self._processed_image = None
97
97
  self._processed_matrix = None
98
98
  self._process_image_failed = False
99
- self._processing_message = None
99
+ self.message = None
100
100
  if self.operations or self.dither or self.prevent_crop:
101
101
  step = UNITS_PER_INCH / self.dpi
102
102
  step_x = step
@@ -141,6 +141,9 @@ class ImageNode(Node):
141
141
  self.set_dirty_bounds()
142
142
  self.process_image(self.step_x, self.step_y, not self.prevent_crop)
143
143
 
144
+ def as_image(self):
145
+ return self.active_image, self.bbox()
146
+
144
147
  def bbox(self, transformed=True, with_stroke=False):
145
148
  image_width, image_height = self.active_image.size
146
149
  matrix = self.active_matrix
@@ -212,7 +215,7 @@ class ImageNode(Node):
212
215
  """
213
216
  self._needs_update = True
214
217
  if context is not None:
215
- self._processing_message = "Processing..."
218
+ self.message = "Processing..."
216
219
  context.signal("refresh_scene", "Scene")
217
220
  if self._update_thread is None:
218
221
 
@@ -221,11 +224,9 @@ class ImageNode(Node):
221
224
  self._update_thread = None
222
225
  if context is not None:
223
226
  if self._process_image_failed:
224
- self._processing_message = (
225
- "Process image could not exist in memory."
226
- )
227
+ self.message = "Process image could not exist in memory."
227
228
  else:
228
- self._processing_message = None
229
+ self.message = None
229
230
  context.signal("refresh_scene", "Scene")
230
231
  context.signal("image_updated", self)
231
232
 
@@ -293,10 +294,16 @@ class ImageNode(Node):
293
294
  bb = self.bbox()
294
295
  self._bounds = bb
295
296
  self._paint_bounds = bb
296
- except (MemoryError, Image.DecompressionBombError, ValueError):
297
+ except (
298
+ MemoryError,
299
+ Image.DecompressionBombError,
300
+ ValueError,
301
+ ZeroDivisionError,
302
+ ):
297
303
  # Memory error if creating requires too much memory.
298
304
  # DecompressionBomb if over 272 megapixels.
299
305
  # ValueError if bounds are NaN.
306
+ # ZeroDivide if inverting the processed matrix cannot happen because image is a line
300
307
  self._process_image_failed = True
301
308
  self.updated()
302
309
 
@@ -574,6 +581,20 @@ class ImageNode(Node):
574
581
  """
575
582
  from PIL import Image, ImageOps
576
583
 
584
+ try:
585
+ from PIL.Image import Transform
586
+
587
+ AFFINE = Transform.AFFINE
588
+ except ImportError:
589
+ AFFINE = Image.AFFINE
590
+
591
+ try:
592
+ from PIL.Image import Resampling
593
+
594
+ BICUBIC = Resampling.BICUBIC
595
+ except ImportError:
596
+ BICUBIC = Image.BICUBIC
597
+
577
598
  image = self.image
578
599
 
579
600
  transparent_mask = self._get_transparent_mask(image)
@@ -589,6 +610,7 @@ class ImageNode(Node):
589
610
  if box is None:
590
611
  # If box is entirely white, bbox caused value error, or crop not set.
591
612
  box = (0, 0, image.width, image.height)
613
+ orgbox = (box[0], box[1], box[2], box[3])
592
614
 
593
615
  transform_matrix = copy(self.matrix) # Prevent Knock-on effect.
594
616
 
@@ -612,6 +634,8 @@ class ImageNode(Node):
612
634
  image_height = ceil(bbox[3] * step_scale_y) - floor(bbox[1] * step_scale_y)
613
635
  tx = bbox[0]
614
636
  ty = bbox[1]
637
+ # Caveat: we move the picture backward, so that the non-white
638
+ # image content aligns at 0 , 0 - but we don't crop the image
615
639
  transform_matrix.post_translate(-tx, -ty)
616
640
  transform_matrix.post_scale(step_scale_x, step_scale_y)
617
641
  if step_y < 0:
@@ -640,7 +664,7 @@ class ImageNode(Node):
640
664
  image_width = 1
641
665
  image = image.transform(
642
666
  (image_width, image_height),
643
- Image.AFFINE,
667
+ AFFINE,
644
668
  (
645
669
  transform_matrix.a,
646
670
  transform_matrix.c,
@@ -649,21 +673,11 @@ class ImageNode(Node):
649
673
  transform_matrix.d,
650
674
  transform_matrix.f,
651
675
  ),
652
- resample=Image.BICUBIC,
676
+ resample=BICUBIC,
653
677
  fillcolor="black" if self.invert else "white",
654
678
  )
655
679
  actualized_matrix = Matrix()
656
680
 
657
- # If crop applies, apply crop.
658
- if crop:
659
- box = self._get_crop_box(image)
660
- if box is not None:
661
- width = box[2] - box[0]
662
- height = box[3] - box[1]
663
- if width != image.width or height != image.height:
664
- image = image.crop(box)
665
- actualized_matrix.post_translate(box[0], box[1])
666
-
667
681
  if step_y < 0:
668
682
  # if step_y is negative, translate.
669
683
  actualized_matrix.post_translate(0, -image_height)
@@ -671,6 +685,22 @@ class ImageNode(Node):
671
685
  # if step_x is negative, translate.
672
686
  actualized_matrix.post_translate(-image_width, 0)
673
687
 
688
+ # If crop applies, apply crop.
689
+ if crop:
690
+ cbox = self._get_crop_box(image)
691
+ if cbox is not None:
692
+ width = cbox[2] - cbox[0]
693
+ height = cbox[3] - cbox[1]
694
+ if width != image.width or height != image.height:
695
+ image = image.crop(cbox)
696
+ # TODO:
697
+ # We did not crop the image so far, but we already applied
698
+ # the cropped transformation! That may be faulty, and needs to
699
+ # be corrected at a later stage, but this logic, even if clumsy
700
+ # is good enough: don't shift things twice!
701
+ if orgbox[0] == 0 and orgbox[1] == 0:
702
+ actualized_matrix.post_translate(cbox[0], cbox[1])
703
+
674
704
  actualized_matrix.post_scale(step_x, step_y)
675
705
  actualized_matrix.post_translate(tx, ty)
676
706
 
@@ -72,6 +72,18 @@ class LineNode(Node, Stroked, FunctionalParameter):
72
72
  self.stroke_width_zero()
73
73
 
74
74
  self.set_dirty_bounds()
75
+ self.functional_parameter = (
76
+ "line",
77
+ 0,
78
+ self.x1,
79
+ self.y1,
80
+ 0,
81
+ self.x2,
82
+ self.y2,
83
+ 0,
84
+ (self.x1 + self.x2) / 2.0,
85
+ (self.y1 + self.y2) / 2.0,
86
+ )
75
87
 
76
88
  def __copy__(self):
77
89
  nd = self.node_dict
@@ -230,3 +242,51 @@ class LineNode(Node, Stroked, FunctionalParameter):
230
242
  SVG_VALUE_NON_SCALING_STROKE if not self.stroke_scale else ""
231
243
  )
232
244
  return path
245
+
246
+ @property
247
+ def functional_parameter(self):
248
+ return self.mkparam
249
+
250
+ @functional_parameter.setter
251
+ def functional_parameter(self, value):
252
+ def getit(data, idx, default):
253
+ if idx < len(data):
254
+ return data[idx]
255
+ else:
256
+ return default
257
+
258
+ if isinstance(value, (list, tuple)):
259
+ self.mkparam = value
260
+ if self.mkparam:
261
+ method = self.mkparam[0]
262
+
263
+ cx = (self.x1 + self.x2) / 2
264
+ cy = (self.y1 + self.y2) / 2
265
+ mx = getit(self.mkparam, 8, cx)
266
+ my = getit(self.mkparam, 9, cy)
267
+
268
+ if self.x1 != self.mkparam[2] or self.y1 != self.mkparam[3]:
269
+ # Start changed.
270
+ self.x1 = getit(self.mkparam, 2, self.x1)
271
+ self.y1 = getit(self.mkparam, 3, self.y1)
272
+ self.mkparam[8] = cx
273
+ self.mkparam[9] = cy
274
+ elif self.x2 != self.mkparam[5] or self.y2 != self.mkparam[6]:
275
+ # End changed
276
+ self.x2 = getit(self.mkparam, 5, self.x2)
277
+ self.y2 = getit(self.mkparam, 6, self.y2)
278
+ self.mkparam[8] = cx
279
+ self.mkparam[9] = cy
280
+ elif cx != mx or cy != my:
281
+ # Midpoint changed.
282
+ dx = mx - cx
283
+ dy = my - cy
284
+ self.x1 += dx
285
+ self.y1 += dy
286
+ self.x2 += dx
287
+ self.y2 += dy
288
+ self.mkparam[2] = self.x1
289
+ self.mkparam[3] = self.y1
290
+ self.mkparam[5] = self.x2
291
+ self.mkparam[6] = self.y2
292
+ self.altered()
@@ -251,12 +251,14 @@ class RectNode(Node, Stroked, FunctionalParameter):
251
251
  @property
252
252
  def functional_parameter(self):
253
253
  dimens = 0.5 * min(self.width, self.height)
254
+ try:
255
+ k = min(1.0, self.rx / dimens)
256
+ except ZeroDivisionError:
257
+ k = 0.0
254
258
  return (
255
259
  "rect",
256
260
  2,
257
- min(1.0, self.rx / dimens),
258
- # 2,
259
- # min(1.0, self.ry / self.height),
261
+ k,
260
262
  )
261
263
 
262
264
  @functional_parameter.setter