Skip to content

Commit 4ec59ab

Browse files
authored
Merge pull request #18 from plottertools/inversion-xy
Restore Invert X and Y
2 parents 1453829 + 63c381a commit 4ec59ab

File tree

4 files changed

+56
-2
lines changed

4 files changed

+56
-2
lines changed

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@ These parameters define the transformation between *vpype*'s and the target's co
7979
- `scale_y`: Apply a scaling factor on the Y axis. Use `-1` to invert the direction.
8080
- `offset_x`: Apply an offset to the X axis. This offset is expressed in the unit defined by `unit`.
8181
- `offset_y`: Apply an offset to the Y axis. This offset is expressed in the unit defined by `unit`.
82+
- `invert_x`: Invert or mirror all points right-to-left without changing the position within the document space.
83+
- `invert_y`: Invert or mirror all points top-to-bottom without changing the position within the document space.
8284

8385
### Output Format
8486
All of the options below default to an empty text which means no output is generated. However, if `segment_first` or `segment_last` is omitted the code from `segment` is used. If there is only one segment, `segment_first` takes priority over `segment_last`.
@@ -119,6 +121,8 @@ The segments accept a lot of values that may be useful statistics for various fo
119121

120122
Note: `idx` and `idy` are properly guarded against compounding fractional rounding errors. Moving 0.1 units 1000 times results in a location 100 units away and not zero.
121123

124+
### Information Control
125+
- `info`: prints text after file is written to inform the user of said information
122126

123127
## Output structure
124128
The gwrite command gives you access to write to a variety of formats that fit the given outline. We're writing generic ascii. Since gcode can have more flavors than a Baskin Robbins™, it's best to simply draw broad strokes as to what ascii output should look like. Here we define the various elements without any regard to the gcode it will largely be producing.
@@ -284,3 +288,4 @@ Which is valid JSON.
284288
# Thanks
285289
* abey76 - Helped with advice that largely pushes us towards the integration goals as well as his very solid suggestion to use .format() which greatly expands the expected formats.
286290
* theomega - Basically rewrote the thing into the dapper codebase you see today. Rather than the 4 hours I figured I'd kill on this.
291+
* ithinkido - For his many insightful comments and determination to make this project as good as it can be.

setup.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
setup(
77
name="vpype-gcode",
8-
version="0.9.1",
8+
version="0.10.0",
99
description="vpype gcode plugin",
1010
long_description=readme,
1111
long_description_content_type="text/markdown",
@@ -16,6 +16,11 @@
1616
classifiers=(
1717
"Programming Language :: Python :: 3.6",
1818
"Programming Language :: Python :: 3.7",
19+
"Programming Language :: Python :: 3.8",
20+
"Programming Language :: Python :: 3.9",
21+
"Environment :: Console",
22+
"Topic :: Artistic Software",
23+
"Topic :: Multimedia :: Graphics",
1924
"License :: OSI Approved :: MIT License",
2025
"Operating System :: OS Independent",
2126
),

vpype_gcode/bundled_configs.toml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,26 @@ segment_first = "G00 X{x:.4f} Y{y:.4f}\n"
55
segment = "G01 X{x:.4f} Y{y:.4f}\n"
66
document_end = "M2\n"
77
unit = "in"
8+
invert_y = "True"
9+
info= "This gcode profile is correctly inverted across the y-axis"
810

911
[gwrite.gcodemm]
1012
document_start = "G21\nG17\nG90\n"
1113
segment_first = "G00 X{x:.4f} Y{y:.4f}\n"
1214
segment = "G01 X{x:.4f} Y{y:.4f}\n"
1315
document_end = "M2\n"
1416
unit = "mm"
17+
invert_y = "True"
18+
info= "This gcode profile is correctly inverted across the y-axis"
1519

1620
[gwrite.gcode_relative]
1721
document_start = "G20\nG17\nG91\n"
1822
segment_first = "G00 X{dx:.4f} Y{dy:.4f}\n"
1923
segment = "G01 X{dx:.4f} Y{dy:.4f}\n"
2024
document_end = "M2\n"
2125
unit = "in"
26+
invert_y = "True"
27+
info= "This gcode profile is correctly inverted across the y-axis"
2228

2329
[gwrite.csv]
2430
document_start = "#Operation, X-value, Y-value\n"

vpype_gcode/gwrite.py

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,33 @@
66
import vpype as vp
77

88
# Load the default config
9+
910
vp.CONFIG_MANAGER.load_config_file(str(Path(__file__).parent / "bundled_configs.toml"))
1011

1112

13+
def invert_axis(document: vp.Document, invert_x: bool, invert_y: bool):
14+
"""Inverts none, one or both axis of the document.
15+
This applies a relative scale operation with factors of 1 or -1
16+
on the two axis to all layers. The inversion happens relative to
17+
the center of the bounds.
18+
"""
19+
20+
bounds = document.bounds()
21+
if not bounds:
22+
return document
23+
24+
origin = (
25+
0.5 * (bounds[0] + bounds[2]),
26+
0.5 * (bounds[1] + bounds[3]),
27+
)
28+
29+
document.translate(-origin[0], -origin[1])
30+
document.scale(-1 if invert_x else 1, -1 if invert_y else 1)
31+
document.translate(origin[0], origin[1])
32+
33+
return document
34+
35+
1236
@click.command()
1337
@click.argument("output", type=click.File("w"))
1438
@click.option(
@@ -21,6 +45,12 @@
2145
)
2246
@vp.global_processor
2347
def gwrite(document: vp.Document, output: typing.TextIO, profile: str):
48+
"""
49+
Write gcode or other ascii files for the vpype pipeline.
50+
51+
The output format can be customized by the user heavily to an extent that you can also output most known
52+
non-gcode ascii text files.
53+
"""
2454
gwrite_config = vp.CONFIG_MANAGER.config["gwrite"]
2555

2656
# If no profile was provided, try to use a default
@@ -73,6 +103,12 @@ def gwrite(document: vp.Document, output: typing.TextIO, profile: str):
73103
document.scale(scale_x / unit_scale, scale_y / unit_scale)
74104
document.translate(offset_x, offset_y)
75105

106+
invert_x = config.get("invert_x", False)
107+
invert_y = config.get("invert_y", False)
108+
# transform the document according to inversion parameters
109+
if invert_x or invert_y:
110+
document = invert_axis(document, invert_x, invert_y)
111+
76112
# process file
77113
filename = output.name
78114
if document_start is not None:
@@ -187,7 +223,9 @@ def gwrite(document: vp.Document, output: typing.TextIO, profile: str):
187223
output.write(document_end.format(filename=filename))
188224
output.flush()
189225
output.close()
190-
226+
info = config.get("info", None)
227+
if info:
228+
print(info)
191229
return orig_document
192230

193231

0 commit comments

Comments
 (0)