meerk40t 0.9.3001__py2.py3-none-any.whl → 0.9.7010__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.
- meerk40t/__init__.py +1 -1
- meerk40t/balormk/balor_params.py +167 -167
- meerk40t/balormk/clone_loader.py +457 -457
- meerk40t/balormk/controller.py +1566 -1512
- meerk40t/balormk/cylindermod.py +64 -0
- meerk40t/balormk/device.py +966 -1959
- meerk40t/balormk/driver.py +778 -591
- meerk40t/balormk/galvo_commands.py +1195 -0
- meerk40t/balormk/gui/balorconfig.py +237 -111
- meerk40t/balormk/gui/balorcontroller.py +191 -184
- meerk40t/balormk/gui/baloroperationproperties.py +116 -115
- meerk40t/balormk/gui/corscene.py +845 -0
- meerk40t/balormk/gui/gui.py +179 -147
- meerk40t/balormk/livelightjob.py +466 -382
- meerk40t/balormk/mock_connection.py +131 -109
- meerk40t/balormk/plugin.py +133 -135
- meerk40t/balormk/usb_connection.py +306 -301
- meerk40t/camera/__init__.py +1 -1
- meerk40t/camera/camera.py +514 -397
- meerk40t/camera/gui/camerapanel.py +1241 -1095
- meerk40t/camera/gui/gui.py +58 -58
- meerk40t/camera/plugin.py +441 -399
- meerk40t/ch341/__init__.py +27 -27
- meerk40t/ch341/ch341device.py +628 -628
- meerk40t/ch341/libusb.py +595 -589
- meerk40t/ch341/mock.py +171 -171
- meerk40t/ch341/windriver.py +157 -157
- meerk40t/constants.py +13 -0
- meerk40t/core/__init__.py +1 -1
- meerk40t/core/bindalias.py +550 -539
- meerk40t/core/core.py +47 -47
- meerk40t/core/cutcode/cubiccut.py +73 -73
- meerk40t/core/cutcode/cutcode.py +315 -312
- meerk40t/core/cutcode/cutgroup.py +141 -137
- meerk40t/core/cutcode/cutobject.py +192 -185
- meerk40t/core/cutcode/dwellcut.py +37 -37
- meerk40t/core/cutcode/gotocut.py +29 -29
- meerk40t/core/cutcode/homecut.py +29 -29
- meerk40t/core/cutcode/inputcut.py +34 -34
- meerk40t/core/cutcode/linecut.py +33 -33
- meerk40t/core/cutcode/outputcut.py +34 -34
- meerk40t/core/cutcode/plotcut.py +335 -335
- meerk40t/core/cutcode/quadcut.py +61 -61
- meerk40t/core/cutcode/rastercut.py +168 -148
- meerk40t/core/cutcode/waitcut.py +34 -34
- meerk40t/core/cutplan.py +1843 -1316
- meerk40t/core/drivers.py +330 -329
- meerk40t/core/elements/align.py +801 -669
- meerk40t/core/elements/branches.py +1844 -1507
- meerk40t/core/elements/clipboard.py +229 -219
- meerk40t/core/elements/element_treeops.py +4561 -2837
- meerk40t/core/elements/element_types.py +125 -105
- meerk40t/core/elements/elements.py +4329 -3617
- meerk40t/core/elements/files.py +117 -64
- meerk40t/core/elements/geometry.py +473 -224
- meerk40t/core/elements/grid.py +467 -316
- meerk40t/core/elements/materials.py +158 -94
- meerk40t/core/elements/notes.py +50 -38
- meerk40t/core/elements/offset_clpr.py +933 -912
- meerk40t/core/elements/offset_mk.py +963 -955
- meerk40t/core/elements/penbox.py +339 -267
- meerk40t/core/elements/placements.py +300 -83
- meerk40t/core/elements/render.py +785 -687
- meerk40t/core/elements/shapes.py +2618 -2092
- meerk40t/core/elements/trace.py +651 -563
- meerk40t/core/elements/tree_commands.py +415 -409
- meerk40t/core/elements/undo_redo.py +116 -58
- meerk40t/core/elements/wordlist.py +319 -200
- meerk40t/core/exceptions.py +9 -9
- meerk40t/core/laserjob.py +220 -220
- meerk40t/core/logging.py +63 -63
- meerk40t/core/node/blobnode.py +83 -86
- meerk40t/core/node/bootstrap.py +105 -103
- meerk40t/core/node/branch_elems.py +40 -31
- meerk40t/core/node/branch_ops.py +45 -38
- meerk40t/core/node/branch_regmark.py +48 -41
- meerk40t/core/node/cutnode.py +29 -32
- meerk40t/core/node/effect_hatch.py +375 -257
- meerk40t/core/node/effect_warp.py +398 -0
- meerk40t/core/node/effect_wobble.py +441 -309
- meerk40t/core/node/elem_ellipse.py +404 -309
- meerk40t/core/node/elem_image.py +1082 -801
- meerk40t/core/node/elem_line.py +358 -292
- meerk40t/core/node/elem_path.py +259 -201
- meerk40t/core/node/elem_point.py +129 -102
- meerk40t/core/node/elem_polyline.py +310 -246
- meerk40t/core/node/elem_rect.py +376 -286
- meerk40t/core/node/elem_text.py +445 -418
- meerk40t/core/node/filenode.py +59 -40
- meerk40t/core/node/groupnode.py +138 -74
- meerk40t/core/node/image_processed.py +777 -766
- meerk40t/core/node/image_raster.py +156 -113
- meerk40t/core/node/layernode.py +31 -31
- meerk40t/core/node/mixins.py +135 -107
- meerk40t/core/node/node.py +1427 -1304
- meerk40t/core/node/nutils.py +117 -114
- meerk40t/core/node/op_cut.py +462 -335
- meerk40t/core/node/op_dots.py +296 -251
- meerk40t/core/node/op_engrave.py +414 -311
- meerk40t/core/node/op_image.py +755 -369
- meerk40t/core/node/op_raster.py +787 -522
- meerk40t/core/node/place_current.py +37 -40
- meerk40t/core/node/place_point.py +329 -126
- meerk40t/core/node/refnode.py +58 -47
- meerk40t/core/node/rootnode.py +225 -219
- meerk40t/core/node/util_console.py +48 -48
- meerk40t/core/node/util_goto.py +84 -65
- meerk40t/core/node/util_home.py +61 -61
- meerk40t/core/node/util_input.py +102 -102
- meerk40t/core/node/util_output.py +102 -102
- meerk40t/core/node/util_wait.py +65 -65
- meerk40t/core/parameters.py +709 -707
- meerk40t/core/planner.py +875 -785
- meerk40t/core/plotplanner.py +656 -652
- meerk40t/core/space.py +120 -113
- meerk40t/core/spoolers.py +706 -705
- meerk40t/core/svg_io.py +1836 -1549
- meerk40t/core/treeop.py +534 -445
- meerk40t/core/undos.py +278 -124
- meerk40t/core/units.py +784 -680
- meerk40t/core/view.py +393 -322
- meerk40t/core/webhelp.py +62 -62
- meerk40t/core/wordlist.py +513 -504
- meerk40t/cylinder/cylinder.py +247 -0
- meerk40t/cylinder/gui/cylindersettings.py +41 -0
- meerk40t/cylinder/gui/gui.py +24 -0
- meerk40t/device/__init__.py +1 -1
- meerk40t/device/basedevice.py +322 -123
- meerk40t/device/devicechoices.py +50 -0
- meerk40t/device/dummydevice.py +163 -128
- meerk40t/device/gui/defaultactions.py +618 -602
- meerk40t/device/gui/effectspanel.py +114 -0
- meerk40t/device/gui/formatterpanel.py +253 -290
- meerk40t/device/gui/warningpanel.py +337 -260
- meerk40t/device/mixins.py +13 -13
- meerk40t/dxf/__init__.py +1 -1
- meerk40t/dxf/dxf_io.py +766 -554
- meerk40t/dxf/plugin.py +47 -35
- meerk40t/external_plugins.py +79 -79
- meerk40t/external_plugins_build.py +28 -28
- meerk40t/extra/cag.py +112 -116
- meerk40t/extra/coolant.py +403 -0
- meerk40t/extra/encode_detect.py +198 -0
- meerk40t/extra/ezd.py +1165 -1165
- meerk40t/extra/hershey.py +835 -340
- meerk40t/extra/imageactions.py +322 -316
- meerk40t/extra/inkscape.py +630 -622
- meerk40t/extra/lbrn.py +424 -424
- meerk40t/extra/outerworld.py +284 -0
- meerk40t/extra/param_functions.py +1542 -1556
- meerk40t/extra/potrace.py +257 -253
- meerk40t/extra/serial_exchange.py +118 -0
- meerk40t/extra/updater.py +602 -453
- meerk40t/extra/vectrace.py +147 -146
- meerk40t/extra/winsleep.py +83 -83
- meerk40t/extra/xcs_reader.py +597 -0
- meerk40t/fill/fills.py +781 -335
- meerk40t/fill/patternfill.py +1061 -1061
- meerk40t/fill/patterns.py +614 -567
- meerk40t/grbl/control.py +87 -87
- meerk40t/grbl/controller.py +990 -903
- meerk40t/grbl/device.py +1081 -768
- meerk40t/grbl/driver.py +989 -771
- meerk40t/grbl/emulator.py +532 -497
- meerk40t/grbl/gcodejob.py +783 -767
- meerk40t/grbl/gui/grblconfiguration.py +373 -298
- meerk40t/grbl/gui/grblcontroller.py +485 -271
- meerk40t/grbl/gui/grblhardwareconfig.py +269 -153
- meerk40t/grbl/gui/grbloperationconfig.py +105 -0
- meerk40t/grbl/gui/gui.py +147 -116
- meerk40t/grbl/interpreter.py +44 -44
- meerk40t/grbl/loader.py +22 -22
- meerk40t/grbl/mock_connection.py +56 -56
- meerk40t/grbl/plugin.py +294 -264
- meerk40t/grbl/serial_connection.py +93 -88
- meerk40t/grbl/tcp_connection.py +81 -79
- meerk40t/grbl/ws_connection.py +112 -0
- meerk40t/gui/__init__.py +1 -1
- meerk40t/gui/about.py +2042 -296
- meerk40t/gui/alignment.py +1644 -1608
- meerk40t/gui/autoexec.py +199 -0
- meerk40t/gui/basicops.py +791 -670
- meerk40t/gui/bufferview.py +77 -71
- meerk40t/gui/busy.py +170 -133
- meerk40t/gui/choicepropertypanel.py +1673 -1469
- meerk40t/gui/consolepanel.py +706 -542
- meerk40t/gui/devicepanel.py +687 -581
- meerk40t/gui/dialogoptions.py +110 -107
- meerk40t/gui/executejob.py +316 -306
- meerk40t/gui/fonts.py +90 -90
- meerk40t/gui/functionwrapper.py +252 -0
- meerk40t/gui/gui_mixins.py +729 -0
- meerk40t/gui/guicolors.py +205 -182
- meerk40t/gui/help_assets/help_assets.py +218 -201
- meerk40t/gui/helper.py +154 -0
- meerk40t/gui/hersheymanager.py +1430 -846
- meerk40t/gui/icons.py +3422 -2747
- meerk40t/gui/imagesplitter.py +555 -508
- meerk40t/gui/keymap.py +354 -344
- meerk40t/gui/laserpanel.py +892 -806
- meerk40t/gui/laserrender.py +1470 -1232
- meerk40t/gui/lasertoolpanel.py +805 -793
- meerk40t/gui/magnetoptions.py +436 -0
- meerk40t/gui/materialmanager.py +2917 -0
- meerk40t/gui/materialtest.py +1722 -1694
- meerk40t/gui/mkdebug.py +646 -359
- meerk40t/gui/mwindow.py +163 -140
- meerk40t/gui/navigationpanels.py +2605 -2467
- meerk40t/gui/notes.py +143 -142
- meerk40t/gui/opassignment.py +414 -410
- meerk40t/gui/operation_info.py +310 -299
- meerk40t/gui/plugin.py +494 -328
- meerk40t/gui/position.py +714 -669
- meerk40t/gui/preferences.py +901 -650
- meerk40t/gui/propertypanels/attributes.py +1461 -1131
- meerk40t/gui/propertypanels/blobproperty.py +117 -114
- meerk40t/gui/propertypanels/consoleproperty.py +83 -80
- meerk40t/gui/propertypanels/gotoproperty.py +77 -0
- meerk40t/gui/propertypanels/groupproperties.py +223 -217
- meerk40t/gui/propertypanels/hatchproperty.py +489 -469
- meerk40t/gui/propertypanels/imageproperty.py +2244 -1384
- meerk40t/gui/propertypanels/inputproperty.py +59 -58
- meerk40t/gui/propertypanels/opbranchproperties.py +82 -80
- meerk40t/gui/propertypanels/operationpropertymain.py +1890 -1638
- meerk40t/gui/propertypanels/outputproperty.py +59 -58
- meerk40t/gui/propertypanels/pathproperty.py +389 -380
- meerk40t/gui/propertypanels/placementproperty.py +1214 -383
- meerk40t/gui/propertypanels/pointproperty.py +140 -136
- meerk40t/gui/propertypanels/propertywindow.py +313 -181
- meerk40t/gui/propertypanels/rasterwizardpanels.py +996 -912
- meerk40t/gui/propertypanels/regbranchproperties.py +76 -0
- meerk40t/gui/propertypanels/textproperty.py +770 -755
- meerk40t/gui/propertypanels/waitproperty.py +56 -55
- meerk40t/gui/propertypanels/warpproperty.py +121 -0
- meerk40t/gui/propertypanels/wobbleproperty.py +255 -204
- meerk40t/gui/ribbon.py +2468 -2210
- meerk40t/gui/scene/scene.py +1100 -1051
- meerk40t/gui/scene/sceneconst.py +22 -22
- meerk40t/gui/scene/scenepanel.py +439 -349
- meerk40t/gui/scene/scenespacewidget.py +365 -365
- meerk40t/gui/scene/widget.py +518 -505
- meerk40t/gui/scenewidgets/affinemover.py +215 -215
- meerk40t/gui/scenewidgets/attractionwidget.py +315 -309
- meerk40t/gui/scenewidgets/bedwidget.py +120 -97
- meerk40t/gui/scenewidgets/elementswidget.py +137 -107
- meerk40t/gui/scenewidgets/gridwidget.py +785 -745
- meerk40t/gui/scenewidgets/guidewidget.py +765 -765
- meerk40t/gui/scenewidgets/laserpathwidget.py +66 -66
- meerk40t/gui/scenewidgets/machineoriginwidget.py +86 -86
- meerk40t/gui/scenewidgets/nodeselector.py +28 -28
- meerk40t/gui/scenewidgets/rectselectwidget.py +589 -346
- meerk40t/gui/scenewidgets/relocatewidget.py +33 -33
- meerk40t/gui/scenewidgets/reticlewidget.py +83 -83
- meerk40t/gui/scenewidgets/selectionwidget.py +2952 -2756
- meerk40t/gui/simpleui.py +357 -333
- meerk40t/gui/simulation.py +2431 -2094
- meerk40t/gui/snapoptions.py +208 -203
- meerk40t/gui/spoolerpanel.py +1227 -1180
- meerk40t/gui/statusbarwidgets/defaultoperations.py +480 -353
- meerk40t/gui/statusbarwidgets/infowidget.py +520 -483
- meerk40t/gui/statusbarwidgets/opassignwidget.py +356 -355
- meerk40t/gui/statusbarwidgets/selectionwidget.py +172 -171
- meerk40t/gui/statusbarwidgets/shapepropwidget.py +754 -236
- meerk40t/gui/statusbarwidgets/statusbar.py +272 -260
- meerk40t/gui/statusbarwidgets/statusbarwidget.py +268 -270
- meerk40t/gui/statusbarwidgets/strokewidget.py +267 -251
- meerk40t/gui/themes.py +200 -78
- meerk40t/gui/tips.py +591 -0
- meerk40t/gui/toolwidgets/circlebrush.py +35 -35
- meerk40t/gui/toolwidgets/toolcircle.py +248 -242
- meerk40t/gui/toolwidgets/toolcontainer.py +82 -77
- meerk40t/gui/toolwidgets/tooldraw.py +97 -90
- meerk40t/gui/toolwidgets/toolellipse.py +219 -212
- meerk40t/gui/toolwidgets/toolimagecut.py +25 -132
- meerk40t/gui/toolwidgets/toolline.py +39 -144
- meerk40t/gui/toolwidgets/toollinetext.py +79 -236
- meerk40t/gui/toolwidgets/toollinetext_inline.py +296 -0
- meerk40t/gui/toolwidgets/toolmeasure.py +160 -216
- meerk40t/gui/toolwidgets/toolnodeedit.py +2088 -2074
- meerk40t/gui/toolwidgets/toolnodemove.py +92 -94
- meerk40t/gui/toolwidgets/toolparameter.py +754 -668
- meerk40t/gui/toolwidgets/toolplacement.py +108 -108
- meerk40t/gui/toolwidgets/toolpoint.py +68 -59
- meerk40t/gui/toolwidgets/toolpointlistbuilder.py +294 -0
- meerk40t/gui/toolwidgets/toolpointmove.py +183 -0
- meerk40t/gui/toolwidgets/toolpolygon.py +288 -403
- meerk40t/gui/toolwidgets/toolpolyline.py +38 -196
- meerk40t/gui/toolwidgets/toolrect.py +211 -207
- meerk40t/gui/toolwidgets/toolrelocate.py +72 -72
- meerk40t/gui/toolwidgets/toolribbon.py +598 -113
- meerk40t/gui/toolwidgets/tooltabedit.py +546 -0
- meerk40t/gui/toolwidgets/tooltext.py +98 -89
- meerk40t/gui/toolwidgets/toolvector.py +213 -204
- meerk40t/gui/toolwidgets/toolwidget.py +39 -39
- meerk40t/gui/usbconnect.py +98 -91
- meerk40t/gui/utilitywidgets/buttonwidget.py +18 -18
- meerk40t/gui/utilitywidgets/checkboxwidget.py +90 -90
- meerk40t/gui/utilitywidgets/controlwidget.py +14 -14
- meerk40t/gui/utilitywidgets/cyclocycloidwidget.py +343 -340
- meerk40t/gui/utilitywidgets/debugwidgets.py +148 -0
- meerk40t/gui/utilitywidgets/handlewidget.py +27 -27
- meerk40t/gui/utilitywidgets/harmonograph.py +450 -447
- meerk40t/gui/utilitywidgets/openclosewidget.py +40 -40
- meerk40t/gui/utilitywidgets/rotationwidget.py +54 -54
- meerk40t/gui/utilitywidgets/scalewidget.py +75 -75
- meerk40t/gui/utilitywidgets/seekbarwidget.py +183 -183
- meerk40t/gui/utilitywidgets/togglewidget.py +142 -142
- meerk40t/gui/utilitywidgets/toolbarwidget.py +8 -8
- meerk40t/gui/wordlisteditor.py +985 -931
- meerk40t/gui/wxmeerk40t.py +1444 -1169
- meerk40t/gui/wxmmain.py +5578 -4112
- meerk40t/gui/wxmribbon.py +1591 -1076
- meerk40t/gui/wxmscene.py +1635 -1453
- meerk40t/gui/wxmtree.py +2410 -2089
- meerk40t/gui/wxutils.py +1769 -1099
- meerk40t/gui/zmatrix.py +102 -102
- meerk40t/image/__init__.py +1 -1
- meerk40t/image/dither.py +429 -0
- meerk40t/image/imagetools.py +2778 -2269
- meerk40t/internal_plugins.py +150 -130
- meerk40t/kernel/__init__.py +63 -12
- meerk40t/kernel/channel.py +259 -212
- meerk40t/kernel/context.py +538 -538
- meerk40t/kernel/exceptions.py +41 -41
- meerk40t/kernel/functions.py +463 -414
- meerk40t/kernel/jobs.py +100 -100
- meerk40t/kernel/kernel.py +3809 -3571
- meerk40t/kernel/lifecycles.py +71 -71
- meerk40t/kernel/module.py +49 -49
- meerk40t/kernel/service.py +147 -147
- meerk40t/kernel/settings.py +383 -343
- meerk40t/lihuiyu/controller.py +883 -876
- meerk40t/lihuiyu/device.py +1181 -1069
- meerk40t/lihuiyu/driver.py +1466 -1372
- meerk40t/lihuiyu/gui/gui.py +127 -106
- meerk40t/lihuiyu/gui/lhyaccelgui.py +377 -363
- meerk40t/lihuiyu/gui/lhycontrollergui.py +741 -651
- meerk40t/lihuiyu/gui/lhydrivergui.py +470 -446
- meerk40t/lihuiyu/gui/lhyoperationproperties.py +238 -237
- meerk40t/lihuiyu/gui/tcpcontroller.py +226 -190
- meerk40t/lihuiyu/interpreter.py +53 -53
- meerk40t/lihuiyu/laserspeed.py +450 -450
- meerk40t/lihuiyu/loader.py +90 -90
- meerk40t/lihuiyu/parser.py +404 -404
- meerk40t/lihuiyu/plugin.py +101 -102
- meerk40t/lihuiyu/tcp_connection.py +111 -109
- meerk40t/main.py +231 -165
- meerk40t/moshi/builder.py +788 -781
- meerk40t/moshi/controller.py +505 -499
- meerk40t/moshi/device.py +495 -442
- meerk40t/moshi/driver.py +862 -696
- meerk40t/moshi/gui/gui.py +78 -76
- meerk40t/moshi/gui/moshicontrollergui.py +538 -522
- meerk40t/moshi/gui/moshidrivergui.py +87 -75
- meerk40t/moshi/plugin.py +43 -43
- meerk40t/network/console_server.py +102 -57
- meerk40t/network/kernelserver.py +10 -9
- meerk40t/network/tcp_server.py +142 -140
- meerk40t/network/udp_server.py +103 -77
- meerk40t/network/web_server.py +390 -0
- meerk40t/newly/controller.py +1158 -1144
- meerk40t/newly/device.py +874 -732
- meerk40t/newly/driver.py +540 -412
- meerk40t/newly/gui/gui.py +219 -188
- meerk40t/newly/gui/newlyconfig.py +116 -101
- meerk40t/newly/gui/newlycontroller.py +193 -186
- meerk40t/newly/gui/operationproperties.py +51 -51
- meerk40t/newly/mock_connection.py +82 -82
- meerk40t/newly/newly_params.py +56 -56
- meerk40t/newly/plugin.py +1214 -1246
- meerk40t/newly/usb_connection.py +322 -322
- meerk40t/rotary/gui/gui.py +52 -46
- meerk40t/rotary/gui/rotarysettings.py +240 -232
- meerk40t/rotary/rotary.py +202 -98
- meerk40t/ruida/control.py +291 -91
- meerk40t/ruida/controller.py +138 -1088
- meerk40t/ruida/device.py +672 -231
- meerk40t/ruida/driver.py +534 -472
- meerk40t/ruida/emulator.py +1494 -1491
- meerk40t/ruida/exceptions.py +4 -4
- meerk40t/ruida/gui/gui.py +71 -76
- meerk40t/ruida/gui/ruidaconfig.py +239 -72
- meerk40t/ruida/gui/ruidacontroller.py +187 -184
- meerk40t/ruida/gui/ruidaoperationproperties.py +48 -47
- meerk40t/ruida/loader.py +54 -52
- meerk40t/ruida/mock_connection.py +57 -109
- meerk40t/ruida/plugin.py +124 -87
- meerk40t/ruida/rdjob.py +2084 -945
- meerk40t/ruida/serial_connection.py +116 -0
- meerk40t/ruida/tcp_connection.py +146 -0
- meerk40t/ruida/udp_connection.py +73 -0
- meerk40t/svgelements.py +9671 -9669
- meerk40t/tools/driver_to_path.py +584 -579
- meerk40t/tools/geomstr.py +5583 -4680
- meerk40t/tools/jhfparser.py +357 -292
- meerk40t/tools/kerftest.py +904 -890
- meerk40t/tools/livinghinges.py +1168 -1033
- meerk40t/tools/pathtools.py +987 -949
- meerk40t/tools/pmatrix.py +234 -0
- meerk40t/tools/pointfinder.py +942 -942
- meerk40t/tools/polybool.py +940 -940
- meerk40t/tools/rasterplotter.py +1660 -547
- meerk40t/tools/shxparser.py +989 -901
- meerk40t/tools/ttfparser.py +726 -446
- meerk40t/tools/zinglplotter.py +595 -593
- {meerk40t-0.9.3001.dist-info → meerk40t-0.9.7010.dist-info}/LICENSE +21 -21
- {meerk40t-0.9.3001.dist-info → meerk40t-0.9.7010.dist-info}/METADATA +150 -139
- meerk40t-0.9.7010.dist-info/RECORD +445 -0
- {meerk40t-0.9.3001.dist-info → meerk40t-0.9.7010.dist-info}/WHEEL +1 -1
- {meerk40t-0.9.3001.dist-info → meerk40t-0.9.7010.dist-info}/top_level.txt +0 -1
- {meerk40t-0.9.3001.dist-info → meerk40t-0.9.7010.dist-info}/zip-safe +1 -1
- meerk40t/balormk/elementlightjob.py +0 -159
- meerk40t-0.9.3001.dist-info/RECORD +0 -437
- test/bootstrap.py +0 -63
- test/test_cli.py +0 -12
- test/test_core_cutcode.py +0 -418
- test/test_core_elements.py +0 -144
- test/test_core_plotplanner.py +0 -397
- test/test_core_viewports.py +0 -312
- test/test_drivers_grbl.py +0 -108
- test/test_drivers_lihuiyu.py +0 -443
- test/test_drivers_newly.py +0 -113
- test/test_element_degenerate_points.py +0 -43
- test/test_elements_classify.py +0 -97
- test/test_elements_penbox.py +0 -22
- test/test_file_svg.py +0 -176
- test/test_fill.py +0 -155
- test/test_geomstr.py +0 -1523
- test/test_geomstr_nodes.py +0 -18
- test/test_imagetools_actualize.py +0 -306
- test/test_imagetools_wizard.py +0 -258
- test/test_kernel.py +0 -200
- test/test_laser_speeds.py +0 -3303
- test/test_length.py +0 -57
- test/test_lifecycle.py +0 -66
- test/test_operations.py +0 -251
- test/test_operations_hatch.py +0 -57
- test/test_ruida.py +0 -19
- test/test_spooler.py +0 -22
- test/test_tools_rasterplotter.py +0 -29
- test/test_wobble.py +0 -133
- test/test_zingl.py +0 -124
- {test → meerk40t/cylinder}/__init__.py +0 -0
- /meerk40t/{core/element_commands.py → cylinder/gui/__init__.py} +0 -0
- {meerk40t-0.9.3001.dist-info → meerk40t-0.9.7010.dist-info}/entry_points.txt +0 -0
meerk40t/core/elements/trace.py
CHANGED
@@ -1,563 +1,651 @@
|
|
1
|
-
"""
|
2
|
-
This
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
#
|
159
|
-
#
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
#
|
182
|
-
R
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
)
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
for
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
#
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
)
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
)
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
hull =
|
527
|
-
elif method == "
|
528
|
-
hull =
|
529
|
-
elif method == "
|
530
|
-
|
531
|
-
elif method == "
|
532
|
-
hull =
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
if
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
1
|
+
"""
|
2
|
+
This module contains a collection of console commands that manage and implement the elements system related to tracing shapes.
|
3
|
+
It provides functionalities for calculating minimum enclosing circles, generating hull shapes, and tracing elements based on various methods.
|
4
|
+
|
5
|
+
Functions:
|
6
|
+
- plugin: Initializes the console commands for the trace system.
|
7
|
+
- dist: Calculates the Euclidean distance between two points.
|
8
|
+
- is_inside: Checks if a point lies inside or on the boundary of a circle.
|
9
|
+
- get_circle_center: Computes the center of a circle defined by three points.
|
10
|
+
- circle_from1: Returns the smallest circle that intersects two points.
|
11
|
+
- circle_from2: Returns a unique circle that intersects three points.
|
12
|
+
- is_valid_circle: Checks if a circle encloses a given set of points.
|
13
|
+
- min_circle_trivial: Returns the minimum enclosing circle for up to three points.
|
14
|
+
- welzl_helper: Implements Welzl's algorithm to find the minimum enclosing circle.
|
15
|
+
- welzl: Finds the minimum enclosing circle using a randomized approach.
|
16
|
+
- generate_hull_shape_segment: Generates a hull shape segment from the provided data.
|
17
|
+
- generate_hull_shape_quick: Quickly generates a bounding box for the provided data.
|
18
|
+
- generate_hull_shape_hull: Generates a convex hull shape from the provided data.
|
19
|
+
- generate_hull_shape_circle_data: Computes the minimum enclosing circle for the provided data.
|
20
|
+
- generate_hull_shape_circle: Generates a circular hull shape based on the minimum enclosing circle.
|
21
|
+
- init_commands: Sets up the console commands related to tracing operations.
|
22
|
+
- trace_trace_spooler: Traces the given elements using a specified method.
|
23
|
+
- trace_trace_generator: Creates a trace around the given elements based on a specified method.
|
24
|
+
|
25
|
+
"""
|
26
|
+
|
27
|
+
from math import cos, isinf, sin, sqrt, tau
|
28
|
+
from random import randint, shuffle
|
29
|
+
|
30
|
+
from meerk40t.core.units import Length
|
31
|
+
from meerk40t.svgelements import Circle, Path, Point, Polyline
|
32
|
+
from meerk40t.tools.geomstr import Geomstr
|
33
|
+
|
34
|
+
def plugin(kernel, lifecycle=None):
|
35
|
+
_ = kernel.translation
|
36
|
+
if lifecycle == "postboot":
|
37
|
+
init_commands(kernel)
|
38
|
+
|
39
|
+
|
40
|
+
def dist(a, b):
|
41
|
+
"""
|
42
|
+
Function to return the Euclidean distance between two points
|
43
|
+
@param a:
|
44
|
+
@param b:
|
45
|
+
@return:
|
46
|
+
"""
|
47
|
+
return sqrt(pow(a[0] - b[0], 2) + pow(a[1] - b[1], 2))
|
48
|
+
|
49
|
+
|
50
|
+
def is_inside(center, radius, p):
|
51
|
+
"""
|
52
|
+
Function to check whether a point lies inside or on the boundaries of the circle
|
53
|
+
@param center:
|
54
|
+
@param radius:
|
55
|
+
@param p:
|
56
|
+
@return:
|
57
|
+
"""
|
58
|
+
return dist(center, p) <= radius
|
59
|
+
|
60
|
+
|
61
|
+
# The following two functions are used
|
62
|
+
# To find the equation of the circle when
|
63
|
+
# three points are given.
|
64
|
+
|
65
|
+
|
66
|
+
def get_circle_center(bx, by, cx, cy):
|
67
|
+
"""
|
68
|
+
Helper method to get a circle defined by 3 points
|
69
|
+
@param bx:
|
70
|
+
@param by:
|
71
|
+
@param cx:
|
72
|
+
@param cy:
|
73
|
+
@return:
|
74
|
+
"""
|
75
|
+
|
76
|
+
B = bx * bx + by * by
|
77
|
+
C = cx * cx + cy * cy
|
78
|
+
D = bx * cy - by * cx
|
79
|
+
return [(cy * B - by * C) / (2 * D), (bx * C - cx * B) / (2 * D)]
|
80
|
+
|
81
|
+
|
82
|
+
def circle_from1(A, B):
|
83
|
+
"""
|
84
|
+
Function to return the smallest circle that intersects 2 points
|
85
|
+
@param A:
|
86
|
+
@param B:
|
87
|
+
@return:
|
88
|
+
"""
|
89
|
+
# Set the center to be the midpoint of A and B
|
90
|
+
C = [(A[0] + B[0]) / 2.0, (A[1] + B[1]) / 2.0]
|
91
|
+
|
92
|
+
# Set the radius to be half the distance AB
|
93
|
+
return C, dist(A, B) / 2.0
|
94
|
+
|
95
|
+
|
96
|
+
def circle_from2(A, B, C):
|
97
|
+
"""
|
98
|
+
Function to return a unique circle that intersects three points
|
99
|
+
@param A:
|
100
|
+
@param B:
|
101
|
+
@param C:
|
102
|
+
@return:
|
103
|
+
"""
|
104
|
+
if A == B:
|
105
|
+
I, radius = circle_from1(A, C)
|
106
|
+
return I, radius
|
107
|
+
elif A == C:
|
108
|
+
I, radius = circle_from1(A, B)
|
109
|
+
return I, radius
|
110
|
+
elif B == C:
|
111
|
+
I, radius = circle_from1(A, B)
|
112
|
+
return I, radius
|
113
|
+
else:
|
114
|
+
I = get_circle_center(B[0] - A[0], B[1] - A[1], C[0] - A[0], C[1] - A[1])
|
115
|
+
I[0] += A[0]
|
116
|
+
I[1] += A[1]
|
117
|
+
radius = dist(I, A)
|
118
|
+
return I, radius
|
119
|
+
|
120
|
+
|
121
|
+
def is_valid_circle(center, radius, P):
|
122
|
+
"""
|
123
|
+
Function to check whether a circle encloses the given points
|
124
|
+
|
125
|
+
@param center:
|
126
|
+
@param radius:
|
127
|
+
@param P:
|
128
|
+
@return:
|
129
|
+
"""
|
130
|
+
|
131
|
+
# Iterating through all the points
|
132
|
+
# to check whether the points
|
133
|
+
# lie inside the circle or not
|
134
|
+
for p in P:
|
135
|
+
if not is_inside(center, radius, p):
|
136
|
+
return False
|
137
|
+
return True
|
138
|
+
|
139
|
+
|
140
|
+
def min_circle_trivial(P):
|
141
|
+
"""
|
142
|
+
Function to return the minimum enclosing circle for N <= 3
|
143
|
+
@param P:
|
144
|
+
@return:
|
145
|
+
"""
|
146
|
+
assert len(P) <= 3
|
147
|
+
|
148
|
+
if not P:
|
149
|
+
return [0, 0], 0
|
150
|
+
|
151
|
+
elif len(P) == 1:
|
152
|
+
return P[0], 0
|
153
|
+
|
154
|
+
elif len(P) == 2:
|
155
|
+
center, radius = circle_from1(P[0], P[1])
|
156
|
+
return center, radius
|
157
|
+
|
158
|
+
# To check if MEC can be determined
|
159
|
+
# by 2 points only
|
160
|
+
for i in range(3):
|
161
|
+
for j in range(i + 1, 3):
|
162
|
+
center, radius = circle_from1(P[i], P[j])
|
163
|
+
if is_valid_circle(center, radius, P):
|
164
|
+
return center, radius
|
165
|
+
|
166
|
+
center, radius = circle_from2(P[0], P[1], P[2])
|
167
|
+
return center, radius
|
168
|
+
|
169
|
+
|
170
|
+
def welzl_helper(P, R, n):
|
171
|
+
"""
|
172
|
+
Returns the MEC using Welzl's algorithm takes a set of input points P and a set R points on the circle boundary.
|
173
|
+
n represents the number of points in P that are not yet processed.
|
174
|
+
|
175
|
+
@param P:
|
176
|
+
@param R:
|
177
|
+
@param n:
|
178
|
+
@return:
|
179
|
+
"""
|
180
|
+
# print (f"Welzl_helper. P={len(P)} pts, R={len(R)} pts, n={n}")
|
181
|
+
# Base case when all points processed or |R| = 3
|
182
|
+
if n <= 0 or len(R) == 3:
|
183
|
+
center, radius = min_circle_trivial(R)
|
184
|
+
return center, radius
|
185
|
+
|
186
|
+
# Pick a random point randomly
|
187
|
+
idx = randint(0, n - 1)
|
188
|
+
p = P[idx]
|
189
|
+
|
190
|
+
# Put the picked point at the end of P
|
191
|
+
# since it's more efficient than
|
192
|
+
# deleting from the middle of the vector
|
193
|
+
P[idx], P[n - 1] = P[n - 1], P[idx]
|
194
|
+
|
195
|
+
# Get the MEC circle d from the
|
196
|
+
# set of points P - :p
|
197
|
+
dcenter, dradius = welzl_helper(P, R.copy(), n - 1)
|
198
|
+
|
199
|
+
# If d contains p, return d
|
200
|
+
if is_inside(dcenter, dradius, p):
|
201
|
+
return dcenter, dradius
|
202
|
+
|
203
|
+
# Otherwise, must be on the boundary of the MEC
|
204
|
+
R.append(p)
|
205
|
+
|
206
|
+
# Return the MEC for P - :p and R U :p
|
207
|
+
dcenter, dradius = welzl_helper(P, R.copy(), n - 1)
|
208
|
+
return dcenter, dradius
|
209
|
+
|
210
|
+
|
211
|
+
def welzl(P):
|
212
|
+
P_copy = P.copy()
|
213
|
+
shuffle(P_copy)
|
214
|
+
center, radius = welzl_helper(P_copy, [], len(P_copy))
|
215
|
+
return center, radius
|
216
|
+
|
217
|
+
|
218
|
+
def generate_hull_shape_segment(data):
|
219
|
+
pts = []
|
220
|
+
for node in data:
|
221
|
+
try:
|
222
|
+
path = node.as_path()
|
223
|
+
except AttributeError:
|
224
|
+
path = None
|
225
|
+
if path is not None:
|
226
|
+
p = path.first_point
|
227
|
+
pts.append(p)
|
228
|
+
for segment in path:
|
229
|
+
p = segment.end
|
230
|
+
pts.append(p)
|
231
|
+
else:
|
232
|
+
bounds = node.bounds
|
233
|
+
if bounds:
|
234
|
+
pts.extend(
|
235
|
+
[
|
236
|
+
(bounds[0], bounds[1]),
|
237
|
+
(bounds[0], bounds[3]),
|
238
|
+
(bounds[2], bounds[1]),
|
239
|
+
(bounds[2], bounds[3]),
|
240
|
+
(bounds[0], bounds[1]),
|
241
|
+
]
|
242
|
+
)
|
243
|
+
return pts
|
244
|
+
|
245
|
+
|
246
|
+
def generate_hull_shape_quick(data):
|
247
|
+
if not data:
|
248
|
+
return []
|
249
|
+
min_val = [float("inf"), float("inf")]
|
250
|
+
max_val = [-float("inf"), -float("inf")]
|
251
|
+
for node in data:
|
252
|
+
bounds = node.bounds
|
253
|
+
if bounds:
|
254
|
+
min_val[0] = min(min_val[0], bounds[0])
|
255
|
+
min_val[1] = min(min_val[1], bounds[1])
|
256
|
+
max_val[0] = max(max_val[0], bounds[2])
|
257
|
+
max_val[1] = max(max_val[1], bounds[3])
|
258
|
+
if isinf(min_val[0]):
|
259
|
+
return []
|
260
|
+
return [
|
261
|
+
(min_val[0], min_val[1]),
|
262
|
+
(max_val[0], min_val[1]),
|
263
|
+
(max_val[0], max_val[1]),
|
264
|
+
(min_val[0], max_val[1]),
|
265
|
+
(min_val[0], min_val[1]),
|
266
|
+
]
|
267
|
+
|
268
|
+
|
269
|
+
def generate_hull_shape_hull(data):
|
270
|
+
# pts = []
|
271
|
+
# for node in data:
|
272
|
+
# if hasattr(node, "convex_hull"):
|
273
|
+
# ghull = node.convex_hull()
|
274
|
+
# if ghull is not None:
|
275
|
+
# for pt in ghull.as_points():
|
276
|
+
# pts.append((pt.real, pt.imag))
|
277
|
+
# continue
|
278
|
+
# try:
|
279
|
+
# path = node.as_path()
|
280
|
+
# p = path.first_point
|
281
|
+
# if p is None:
|
282
|
+
# continue
|
283
|
+
# pts.append(p)
|
284
|
+
# for segment in path:
|
285
|
+
# pts.append(segment.end)
|
286
|
+
# pts.append(p)
|
287
|
+
# except AttributeError:
|
288
|
+
# bounds = node.bounds
|
289
|
+
# if bounds:
|
290
|
+
# pts.extend(
|
291
|
+
# [
|
292
|
+
# (bounds[0], bounds[1]),
|
293
|
+
# (bounds[0], bounds[3]),
|
294
|
+
# (bounds[2], bounds[1]),
|
295
|
+
# (bounds[2], bounds[3]),
|
296
|
+
# ]
|
297
|
+
# )
|
298
|
+
# hull = list(Point.convex_hull(pts))
|
299
|
+
geometry = Geomstr()
|
300
|
+
for node in data:
|
301
|
+
try:
|
302
|
+
e = None
|
303
|
+
if hasattr(node, "convex_hull"):
|
304
|
+
e = node.convex_hull()
|
305
|
+
if e is None:
|
306
|
+
e = node.as_geometry()
|
307
|
+
except AttributeError:
|
308
|
+
continue
|
309
|
+
geometry.append(e)
|
310
|
+
|
311
|
+
# Convert to hull.
|
312
|
+
resolution = float(Length("1mm"))
|
313
|
+
hull = Geomstr.hull(geometry, distance=int(resolution))
|
314
|
+
# cpts = list(hull.as_points())
|
315
|
+
pts = list((p.real, p.imag) for p in hull.as_points())
|
316
|
+
if len(pts) != 0:
|
317
|
+
pts.append(pts[0]) # loop
|
318
|
+
return pts
|
319
|
+
|
320
|
+
"""
|
321
|
+
There is no need for shape_complex any more as the regular hull routine already uses interpolation
|
322
|
+
def generate_hull_shape_complex(data, resolution=None):
|
323
|
+
if resolution is None:
|
324
|
+
resolution = 500 # How coarse / fine shall a subpath be split
|
325
|
+
else:
|
326
|
+
resolution = int(resolution)
|
327
|
+
pts = []
|
328
|
+
for node in data:
|
329
|
+
try:
|
330
|
+
path = node.as_path()
|
331
|
+
|
332
|
+
from numpy import linspace
|
333
|
+
|
334
|
+
for subpath in path.as_subpaths():
|
335
|
+
psp = Path(subpath)
|
336
|
+
p = psp.first_point
|
337
|
+
pts.append(p)
|
338
|
+
positions = linspace(0, 1, num=resolution, endpoint=True)
|
339
|
+
subj = psp.npoint(positions)
|
340
|
+
s = list(map(Point, subj))
|
341
|
+
pts.extend(s)
|
342
|
+
except AttributeError:
|
343
|
+
bounds = node.bounds
|
344
|
+
if bounds:
|
345
|
+
pts.extend(
|
346
|
+
[
|
347
|
+
(bounds[0], bounds[1]),
|
348
|
+
(bounds[0], bounds[3]),
|
349
|
+
(bounds[2], bounds[1]),
|
350
|
+
(bounds[2], bounds[3]),
|
351
|
+
]
|
352
|
+
)
|
353
|
+
hull = list(Point.convex_hull(pts))
|
354
|
+
if len(hull) != 0:
|
355
|
+
hull.append(hull[0]) # loop
|
356
|
+
return hull
|
357
|
+
"""
|
358
|
+
|
359
|
+
def generate_hull_shape_circle_data(data):
|
360
|
+
pts = []
|
361
|
+
for node in data:
|
362
|
+
try:
|
363
|
+
path = node.as_path()
|
364
|
+
except AttributeError:
|
365
|
+
path = None
|
366
|
+
if path is not None:
|
367
|
+
p = path.first_point
|
368
|
+
pts += [p]
|
369
|
+
for segment in path:
|
370
|
+
p = segment.end
|
371
|
+
pts += [p]
|
372
|
+
else:
|
373
|
+
bounds = node.bounds
|
374
|
+
if bounds:
|
375
|
+
pts += [
|
376
|
+
(bounds[0], bounds[1]),
|
377
|
+
(bounds[0], bounds[3]),
|
378
|
+
(bounds[2], bounds[1]),
|
379
|
+
(bounds[2], bounds[3]),
|
380
|
+
]
|
381
|
+
# We could directly call welzl, but for a significant
|
382
|
+
# amount of point this will cause a huge amount
|
383
|
+
# of recursive calls (which will fail)
|
384
|
+
# -> so we apply it to the hull points
|
385
|
+
hull = list(Point.convex_hull(pts))
|
386
|
+
mec_center, mec_radius = welzl(hull)
|
387
|
+
|
388
|
+
# So now we have a circle with (mec[0], mec[1]), and mec_radius
|
389
|
+
return mec_center, mec_radius
|
390
|
+
|
391
|
+
|
392
|
+
def generate_hull_shape_circle(data):
|
393
|
+
mec_center, mec_radius = generate_hull_shape_circle_data(data)
|
394
|
+
|
395
|
+
# So now we have a circle with (mec[0], mec[1]), and mec_radius
|
396
|
+
hull = []
|
397
|
+
RES = 100
|
398
|
+
for i in range(RES):
|
399
|
+
hull += [
|
400
|
+
(
|
401
|
+
mec_center[0] + mec_radius * cos(i / RES * tau),
|
402
|
+
mec_center[1] + mec_radius * sin(i / RES * tau),
|
403
|
+
)
|
404
|
+
]
|
405
|
+
if len(hull) != 0:
|
406
|
+
hull.append(hull[0]) # loop
|
407
|
+
return hull
|
408
|
+
|
409
|
+
|
410
|
+
def init_commands(kernel):
|
411
|
+
self = kernel.elements
|
412
|
+
|
413
|
+
_ = kernel.translation
|
414
|
+
|
415
|
+
choices = [
|
416
|
+
{
|
417
|
+
"attr": "trace_start_method",
|
418
|
+
"object": self,
|
419
|
+
"default": 0,
|
420
|
+
"type": int,
|
421
|
+
"label": _("Delay hull trace"),
|
422
|
+
"tip": _("Establish if and how an element hull trace should wait"),
|
423
|
+
"page": "Laser",
|
424
|
+
"section": "General",
|
425
|
+
"style": "option",
|
426
|
+
"display": (_("Immediate"), _("User confirmation"), _("Delay 5 seconds")),
|
427
|
+
"choices": (0, 1, 2),
|
428
|
+
},
|
429
|
+
]
|
430
|
+
kernel.register_choices("preferences", choices)
|
431
|
+
|
432
|
+
classify_new = self.post_classify
|
433
|
+
|
434
|
+
# ==========
|
435
|
+
# TRACE OPERATIONS
|
436
|
+
# ==========
|
437
|
+
|
438
|
+
@self.console_argument(
|
439
|
+
"method",
|
440
|
+
help=_("Method to use (one of quick, hull, segment, circle)"),
|
441
|
+
)
|
442
|
+
@self.console_argument("resolution")
|
443
|
+
@self.console_option(
|
444
|
+
"start",
|
445
|
+
"s",
|
446
|
+
type=int,
|
447
|
+
help=_("0=immediate, 1=User interaction, 2=wait for 5 seconds"),
|
448
|
+
)
|
449
|
+
@self.console_option(
|
450
|
+
"force",
|
451
|
+
"f",
|
452
|
+
type=bool,
|
453
|
+
action="store_true",
|
454
|
+
help=_("force the inclusion of non-assigned/non-active elements"),
|
455
|
+
)
|
456
|
+
@self.console_command(
|
457
|
+
"trace",
|
458
|
+
help=_("trace the given elements"),
|
459
|
+
input_type=("elements", None),
|
460
|
+
)
|
461
|
+
def trace_trace_spooler(
|
462
|
+
command,
|
463
|
+
channel,
|
464
|
+
_,
|
465
|
+
method=None,
|
466
|
+
resolution=None,
|
467
|
+
start=None,
|
468
|
+
force=None,
|
469
|
+
data=None,
|
470
|
+
**kwargs,
|
471
|
+
):
|
472
|
+
if method is None:
|
473
|
+
method = "quick"
|
474
|
+
if force is None:
|
475
|
+
force = False
|
476
|
+
method = method.lower()
|
477
|
+
if method not in ("segment", "quick", "hull", "circle"):
|
478
|
+
channel(
|
479
|
+
_(
|
480
|
+
"Invalid method, please use one of quick, hull, segment, circle."
|
481
|
+
)
|
482
|
+
)
|
483
|
+
return
|
484
|
+
|
485
|
+
spooler = self.device.spooler
|
486
|
+
if data is None:
|
487
|
+
data = list(self.elems(emphasized=True))
|
488
|
+
if len(data) == 0:
|
489
|
+
channel(_("No elements bounds to trace"))
|
490
|
+
return
|
491
|
+
# Let's see whether there are non-burnable elements
|
492
|
+
target_data = []
|
493
|
+
if force:
|
494
|
+
target_data = [e for e in data]
|
495
|
+
else:
|
496
|
+
unused = 0
|
497
|
+
for node in data:
|
498
|
+
if len(node._references) == 0 and node.type not in ("file", "group"):
|
499
|
+
unused += 1
|
500
|
+
else:
|
501
|
+
will_be_burnt = False
|
502
|
+
for refnode in node._references:
|
503
|
+
op = refnode.parent
|
504
|
+
if op is not None:
|
505
|
+
try:
|
506
|
+
if op.output:
|
507
|
+
will_be_burnt = True
|
508
|
+
break
|
509
|
+
except AttributeError:
|
510
|
+
pass
|
511
|
+
if will_be_burnt:
|
512
|
+
target_data.append(node)
|
513
|
+
else:
|
514
|
+
unused += 1
|
515
|
+
if unused > 0:
|
516
|
+
msg = _(
|
517
|
+
f"There are {unused} elements, that will not be burnt as they are not "
|
518
|
+
+ "contained in ops or are in disabled operations.\n"
|
519
|
+
+ "These will not be considered in the hull!\n"
|
520
|
+
+ "You can force their inclusion with the --force option"
|
521
|
+
).format(unused=unused)
|
522
|
+
channel(msg)
|
523
|
+
if method == "segment":
|
524
|
+
hull = generate_hull_shape_segment(target_data)
|
525
|
+
elif method == "quick":
|
526
|
+
hull = generate_hull_shape_quick(target_data)
|
527
|
+
elif method == "hull":
|
528
|
+
hull = generate_hull_shape_hull(target_data)
|
529
|
+
# elif method == "complex":
|
530
|
+
# hull = generate_hull_shape_complex(target_data, resolution)
|
531
|
+
elif method == "circle":
|
532
|
+
hull = generate_hull_shape_circle(target_data)
|
533
|
+
else:
|
534
|
+
raise ValueError
|
535
|
+
if start is None:
|
536
|
+
# Let's take system default
|
537
|
+
start = self.trace_start_method
|
538
|
+
if start < 0 or start > 2:
|
539
|
+
start = 0
|
540
|
+
if len(hull) == 0:
|
541
|
+
channel(_("No elements bounds to trace."))
|
542
|
+
return
|
543
|
+
|
544
|
+
def run_shape(_spooler, startmethod, _hull):
|
545
|
+
def trace_hull(startmethod=0):
|
546
|
+
if startmethod == 0:
|
547
|
+
# Immediately
|
548
|
+
pass
|
549
|
+
elif startmethod == 1:
|
550
|
+
# Dialog
|
551
|
+
yield "console", 'interrupt "Trace is about to start"'
|
552
|
+
elif startmethod == 2:
|
553
|
+
# Wait for some seconds
|
554
|
+
yield "wait", 5000
|
555
|
+
|
556
|
+
yield "wait_finish"
|
557
|
+
yield "rapid_mode"
|
558
|
+
idx = 0
|
559
|
+
for p in _hull:
|
560
|
+
idx += 1
|
561
|
+
yield (
|
562
|
+
"move_abs",
|
563
|
+
Length(amount=p[0]).length_mm,
|
564
|
+
Length(amount=p[1]).length_mm,
|
565
|
+
)
|
566
|
+
|
567
|
+
_spooler.laserjob(
|
568
|
+
list(trace_hull(startmethod)), label=f"Trace Job: {method}", helper=True
|
569
|
+
)
|
570
|
+
|
571
|
+
run_shape(spooler, start, hull)
|
572
|
+
|
573
|
+
@self.console_argument(
|
574
|
+
"method",
|
575
|
+
help=_("Method to use (one of quick, hull, segment, circle)"),
|
576
|
+
)
|
577
|
+
@self.console_argument(
|
578
|
+
"resolution", help=_("Resolution for complex slicing, default=500")
|
579
|
+
)
|
580
|
+
@self.console_command(
|
581
|
+
"tracegen",
|
582
|
+
help=_("create the trace around the given elements"),
|
583
|
+
input_type=("elements", None),
|
584
|
+
output_type="elements",
|
585
|
+
)
|
586
|
+
def trace_trace_generator(
|
587
|
+
command,
|
588
|
+
channel,
|
589
|
+
_,
|
590
|
+
method=None,
|
591
|
+
resolution=None,
|
592
|
+
data=None,
|
593
|
+
post=None,
|
594
|
+
**kwargs,
|
595
|
+
):
|
596
|
+
if method is None:
|
597
|
+
method = "quick"
|
598
|
+
method = method.lower()
|
599
|
+
if not method in ("segment", "quick", "hull", "circle"):
|
600
|
+
channel(
|
601
|
+
_(
|
602
|
+
"Invalid method, please use one of quick, hull, segment, circle."
|
603
|
+
)
|
604
|
+
)
|
605
|
+
return
|
606
|
+
|
607
|
+
if data is None:
|
608
|
+
data = list(self.elems(emphasized=True))
|
609
|
+
if len(data) == 0:
|
610
|
+
channel(_("No elements bounds to trace"))
|
611
|
+
return
|
612
|
+
shape_type = "elem polyline"
|
613
|
+
if method == "segment":
|
614
|
+
hull = generate_hull_shape_segment(data)
|
615
|
+
elif method == "quick":
|
616
|
+
hull = generate_hull_shape_quick(data)
|
617
|
+
elif method == "hull":
|
618
|
+
hull = generate_hull_shape_hull(data)
|
619
|
+
# elif method == "complex":
|
620
|
+
# hull = generate_hull_shape_complex(data, resolution)
|
621
|
+
elif method == "circle":
|
622
|
+
shape_type = "elem ellipse"
|
623
|
+
s_center, s_radius = generate_hull_shape_circle_data(data)
|
624
|
+
else:
|
625
|
+
raise ValueError
|
626
|
+
if shape_type == "elem polyline":
|
627
|
+
if len(hull) == 0:
|
628
|
+
channel(_("No elements bounds to trace."))
|
629
|
+
return
|
630
|
+
shape = Polyline(hull)
|
631
|
+
if shape.is_degenerate():
|
632
|
+
channel(_("Shape is degenerate."))
|
633
|
+
return "elements", data
|
634
|
+
elif shape_type == "elem ellipse":
|
635
|
+
shape = Circle(cx=s_center[0], cy=s_center[1], rx=s_radius, ry=s_radius)
|
636
|
+
if shape.is_degenerate():
|
637
|
+
channel(_("Shape is degenerate."))
|
638
|
+
return "elements", data
|
639
|
+
node = self.elem_branch.add(shape=shape, type=shape_type)
|
640
|
+
node.stroke = self.default_stroke
|
641
|
+
node.stroke_width = self.default_strokewidth
|
642
|
+
node.fill = self.default_fill
|
643
|
+
node.altered()
|
644
|
+
self.set_emphasis([node])
|
645
|
+
node.focus()
|
646
|
+
data.append(node)
|
647
|
+
# Newly created! Classification needed?
|
648
|
+
post.append(classify_new(data))
|
649
|
+
return "elements", data
|
650
|
+
|
651
|
+
# --------------------------- END COMMANDS ------------------------------
|