convert_svg_string_to_gcode 0.0.0 → 0.0.1
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.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/Gemfile +17 -0
- data/Gemfile.lock +93 -0
- data/config/console.rb +4 -0
- data/convert_svg_string_to_gcode-0.0.0.gem +0 -0
- data/convert_svg_string_to_gcode.gemspec +1 -1
- data/lib/convert_svg_string_to_gcode.rb +7 -7
- data/lib/convert_svg_string_to_gcode/constants/conversion_constants.rb +13 -6
- data/lib/convert_svg_string_to_gcode/constants/plotter_config.rb +10 -0
- data/lib/convert_svg_string_to_gcode/helpers/adjust_svg_commands_for_plotter.rb +64 -32
- data/lib/convert_svg_string_to_gcode/helpers/box_helper.rb +75 -0
- data/lib/convert_svg_string_to_gcode/helpers/create_commands_from_tokens.rb +34 -6
- data/lib/convert_svg_string_to_gcode/helpers/create_gcode_array_from_svg_commands.rb +24 -25
- data/lib/convert_svg_string_to_gcode/helpers/create_gcode_from_gcode_array.rb +2 -2
- data/lib/convert_svg_string_to_gcode/helpers/read_svg_to_string.rb +6 -0
- data/lib/convert_svg_string_to_gcode/models/box.rb +12 -0
- data/lib/convert_svg_string_to_gcode/models/svg_command.rb +64 -0
- data/script/console +3 -0
- data/script/test +3 -0
- data/spec/factory_helper.rb +29 -0
- data/spec/fixtures/spec_constants.rb +16 -0
- data/spec/fixtures/test.svg +4 -0
- data/spec/helpers.rb +36 -0
- data/spec/spec_helper.rb +36 -0
- data/spec/unit/adjust_svg_commands_for_plotter_spec.rb +24 -0
- data/spec/unit/convert_svg_string_to_gcode_spec.rb +13 -0
- data/spec/unit/create_commands_from_token_spec.rb +26 -0
- data/spec/unit/create_gcode_array_from_svg_commands_spec.rb +13 -0
- data/spec/unit/create_gcode_from_gcode_array_spec.rb +13 -0
- data/spec/unit/parse_svg_string_spec.rb +10 -0
- data/spec/unit/read_svg_to_string_spec.rb +11 -0
- data/spec/unit/tokenize_parsed_svg_spec.rb +11 -0
- metadata +26 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 13748aa4d3d130df359a1289a74818dd293fa890
|
4
|
+
data.tar.gz: f9f2d073c74e4b99cbeed2a2ecd0aa23c87b41dd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9df4d2c3e7a31b7cfd1f6ed7ee08a1fd75d0f8378934f970d58677b61e3e962850f8b404e7fddd5df683cdcb78c15ac9480cc103f7b293faef35616c125b42d2
|
7
|
+
data.tar.gz: b8cf68ba6afbb465d94c5453a1e1c4b44262350899f7d50ed0fbeb43e1a297cd0edb8ad462a7c1aca6d3a55cf631684f4657edbf5b6d21220faa4c6e9b30ea0b
|
data/.gitignore
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
.DS_Store
|
data/Gemfile
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
gemspec
|
3
|
+
|
4
|
+
gem 'rake'
|
5
|
+
gem 'nokogiri', '~> 1.6.7'
|
6
|
+
gem 'pry'
|
7
|
+
gem 'pry-nav'
|
8
|
+
gem 'wirb'
|
9
|
+
|
10
|
+
group :test do
|
11
|
+
gem 'activerecord'
|
12
|
+
gem 'database_cleaner'
|
13
|
+
gem 'pg'
|
14
|
+
gem 'rspec'
|
15
|
+
gem 'webmock'
|
16
|
+
gem 'rack-test'
|
17
|
+
end
|
data/Gemfile.lock
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
convert_svg_string_to_gcode (0.0.0)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: https://rubygems.org/
|
8
|
+
specs:
|
9
|
+
activemodel (4.2.6)
|
10
|
+
activesupport (= 4.2.6)
|
11
|
+
builder (~> 3.1)
|
12
|
+
activerecord (4.2.6)
|
13
|
+
activemodel (= 4.2.6)
|
14
|
+
activesupport (= 4.2.6)
|
15
|
+
arel (~> 6.0)
|
16
|
+
activesupport (4.2.6)
|
17
|
+
i18n (~> 0.7)
|
18
|
+
json (~> 1.7, >= 1.7.7)
|
19
|
+
minitest (~> 5.1)
|
20
|
+
thread_safe (~> 0.3, >= 0.3.4)
|
21
|
+
tzinfo (~> 1.1)
|
22
|
+
addressable (2.4.0)
|
23
|
+
arel (6.0.3)
|
24
|
+
builder (3.2.2)
|
25
|
+
coderay (1.1.1)
|
26
|
+
crack (0.4.3)
|
27
|
+
safe_yaml (~> 1.0.0)
|
28
|
+
database_cleaner (1.5.3)
|
29
|
+
diff-lcs (1.2.5)
|
30
|
+
hashdiff (0.3.0)
|
31
|
+
i18n (0.7.0)
|
32
|
+
json (1.8.3)
|
33
|
+
method_source (0.8.2)
|
34
|
+
mini_portile2 (2.0.0)
|
35
|
+
minitest (5.9.0)
|
36
|
+
nokogiri (1.6.7.1)
|
37
|
+
mini_portile2 (~> 2.0.0.rc2)
|
38
|
+
paint (1.0.1)
|
39
|
+
pg (0.18.4)
|
40
|
+
pry (0.10.3)
|
41
|
+
coderay (~> 1.1.0)
|
42
|
+
method_source (~> 0.8.1)
|
43
|
+
slop (~> 3.4)
|
44
|
+
pry-nav (0.2.4)
|
45
|
+
pry (>= 0.9.10, < 0.11.0)
|
46
|
+
rack (1.6.4)
|
47
|
+
rack-test (0.6.3)
|
48
|
+
rack (>= 1.0)
|
49
|
+
rake (10.5.0)
|
50
|
+
rspec (3.4.0)
|
51
|
+
rspec-core (~> 3.4.0)
|
52
|
+
rspec-expectations (~> 3.4.0)
|
53
|
+
rspec-mocks (~> 3.4.0)
|
54
|
+
rspec-core (3.4.4)
|
55
|
+
rspec-support (~> 3.4.0)
|
56
|
+
rspec-expectations (3.4.0)
|
57
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
58
|
+
rspec-support (~> 3.4.0)
|
59
|
+
rspec-mocks (3.4.1)
|
60
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
61
|
+
rspec-support (~> 3.4.0)
|
62
|
+
rspec-support (3.4.1)
|
63
|
+
safe_yaml (1.0.4)
|
64
|
+
slop (3.6.0)
|
65
|
+
thread_safe (0.3.5)
|
66
|
+
tzinfo (1.2.2)
|
67
|
+
thread_safe (~> 0.1)
|
68
|
+
webmock (2.0.2)
|
69
|
+
addressable (>= 2.3.6)
|
70
|
+
crack (>= 0.3.2)
|
71
|
+
hashdiff
|
72
|
+
wirb (2.0.0)
|
73
|
+
paint (>= 0.9, < 2.0)
|
74
|
+
|
75
|
+
PLATFORMS
|
76
|
+
ruby
|
77
|
+
|
78
|
+
DEPENDENCIES
|
79
|
+
activerecord
|
80
|
+
convert_svg_string_to_gcode!
|
81
|
+
database_cleaner
|
82
|
+
nokogiri (~> 1.6.7)
|
83
|
+
pg
|
84
|
+
pry
|
85
|
+
pry-nav
|
86
|
+
rack-test
|
87
|
+
rake
|
88
|
+
rspec
|
89
|
+
webmock
|
90
|
+
wirb
|
91
|
+
|
92
|
+
BUNDLED WITH
|
93
|
+
1.10.6
|
data/config/console.rb
ADDED
Binary file
|
@@ -3,7 +3,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
3
3
|
|
4
4
|
Gem::Specification.new do |s|
|
5
5
|
s.name = 'convert_svg_string_to_gcode'
|
6
|
-
s.version = '0.0.
|
6
|
+
s.version = '0.0.1'
|
7
7
|
s.date = '2016-03-24'
|
8
8
|
s.summary = "Converts SVG paths to GCode strings"
|
9
9
|
s.description = "A gem that converts SVG paths (passed in as strings) into GCode strings"
|
@@ -1,9 +1,9 @@
|
|
1
|
-
require 'convert_svg_string_to_gcode/parse_svg_string'
|
2
|
-
require 'convert_svg_string_to_gcode/tokenize_parsed_svg'
|
3
|
-
require 'convert_svg_string_to_gcode/create_commands_from_tokens'
|
4
|
-
require 'convert_svg_string_to_gcode/adjust_svg_commands_for_plotter'
|
5
|
-
require 'convert_svg_string_to_gcode/create_gcode_array_from_svg_commands'
|
6
|
-
require 'convert_svg_string_to_gcode/create_gcode_from_gcode_array'
|
1
|
+
require 'convert_svg_string_to_gcode/helpers/parse_svg_string'
|
2
|
+
require 'convert_svg_string_to_gcode/helpers/tokenize_parsed_svg'
|
3
|
+
require 'convert_svg_string_to_gcode/helpers/create_commands_from_tokens'
|
4
|
+
require 'convert_svg_string_to_gcode/helpers/adjust_svg_commands_for_plotter'
|
5
|
+
require 'convert_svg_string_to_gcode/helpers/create_gcode_array_from_svg_commands'
|
6
|
+
require 'convert_svg_string_to_gcode/helpers/create_gcode_from_gcode_array'
|
7
7
|
|
8
8
|
class ConvertSVGStringToGCode
|
9
9
|
|
@@ -11,7 +11,7 @@ class ConvertSVGStringToGCode
|
|
11
11
|
parsed_svg = ParseSVGString.perform(svg_as_string)
|
12
12
|
svg_tokens = TokenizeParsedSVG.perform(parsed_svg)
|
13
13
|
svg_commands = CreateCommandsFromTokens.perform(svg_tokens)
|
14
|
-
adjusted_svg_commands = AdjustSVGCommandsForPlotter.perform(svg_commands,
|
14
|
+
adjusted_svg_commands = AdjustSVGCommandsForPlotter.perform(svg_commands, ConversionConstants::PROPORTION)
|
15
15
|
gcode_array = CreateGCodeArrayFromSVGCommands.perform(adjusted_svg_commands)
|
16
16
|
CreateGCodeFromGCodeArray.perform(gcode_array)
|
17
17
|
end
|
@@ -1,9 +1,16 @@
|
|
1
1
|
|
2
2
|
class ConversionConstants
|
3
|
-
MOVE
|
4
|
-
LINE_TO
|
5
|
-
CURVE
|
6
|
-
X_LABELS
|
7
|
-
Y_LABELS
|
8
|
-
|
3
|
+
MOVE = 'M'
|
4
|
+
LINE_TO = 'L'
|
5
|
+
CURVE = 'C'
|
6
|
+
X_LABELS = [:p0x,:p1x,:cp0x,:cp1x,:p0x,:p1x]
|
7
|
+
Y_LABELS = [:p0y,:p1y,:cp0y,:cp1y,:p0y,:p1y]
|
8
|
+
TYPE_LABEL = :type
|
9
|
+
VALID_CMD_ATTRIBUTES = X_LABELS + Y_LABELS << TYPE_LABEL
|
10
|
+
GCODE_COMMANDS = 'CLM'
|
11
|
+
PROPORTION = 0.7
|
12
|
+
STEP = 0.20
|
13
|
+
|
14
|
+
raise TypeError.new('Proportion must be a Float.') if PROPORTION.class != Float
|
15
|
+
raise TypeError.new('Step must be a Float.') if STEP.class != Float
|
9
16
|
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
require 'convert_svg_string_to_gcode/constants/conversion_constants'
|
2
|
+
|
3
|
+
class PlotterConfig
|
4
|
+
ORIGIN_X = "X0.0"
|
5
|
+
ORIGIN_Y = "Y0.0"
|
6
|
+
Z_DOWN = "Z10.0"
|
7
|
+
Z_UP = "Z30.0"
|
8
|
+
HEADER = ["%", "G21", "G00 #{Z_UP}", "G00 X0.0 Y0.0"]
|
9
|
+
FOOTER = ["G00 #{ORIGIN_X} #{ORIGIN_Y} #{Z_UP}", "%"]
|
10
|
+
end
|
@@ -1,57 +1,89 @@
|
|
1
|
+
require 'convert_svg_string_to_gcode/models/svg_command'
|
2
|
+
require 'convert_svg_string_to_gcode/helpers/box_helper'
|
1
3
|
|
2
4
|
class AdjustSVGCommandsForPlotter
|
3
|
-
def self.perform(svg_commands,proportion=
|
4
|
-
skewed_svg_commands
|
5
|
+
def self.perform(svg_commands,proportion=ConversionConstants::PROPORTION)
|
6
|
+
skewed_svg_commands = resize_svg_commands_by_proportion(svg_commands, proportion)
|
5
7
|
min_x, min_y = get_min_x_y(skewed_svg_commands)
|
8
|
+
max_x, max_y = get_max_x_y(skewed_svg_commands)
|
6
9
|
buffered_svg_commands = add_margin_to_svg_commands(skewed_svg_commands, min_x, min_y)
|
10
|
+
optimize_commands(buffered_svg_commands)
|
7
11
|
end
|
8
12
|
|
9
|
-
def self.
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
13
|
+
def self.optimize_commands(svg_commands)
|
14
|
+
grouped_non_move_commands = group_commands_and_remove_moves(svg_commands)
|
15
|
+
ordered_svg_commands = sort_commands_ascending_by_x(grouped_non_move_commands)
|
16
|
+
sorted_svg_commands = BoxHelper.sort_commands_into_boxes(ordered_svg_commands)
|
17
|
+
add_moves_back_to_svg_commands(sorted_svg_commands)
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.resize_svg_commands_by_proportion(svg_commands, proportion)
|
21
|
+
svg_commands.map do |command|
|
22
|
+
command.adjust_by_proportion(proportion)
|
19
23
|
end
|
20
|
-
return skewed_svg_commands, min_x, min_y
|
21
24
|
end
|
22
25
|
|
23
26
|
def self.get_min_x_y(svg_commands)
|
24
27
|
min_x = nil
|
25
28
|
min_y = nil
|
26
|
-
|
27
29
|
svg_commands.map do |command|
|
28
|
-
command.
|
29
|
-
|
30
|
-
min_x = command[key] if !min_x || command[key]<min_x
|
31
|
-
end
|
30
|
+
command_min_x = [command.p0x, command.p1x].min
|
31
|
+
min_x = command_min_x if !min_x || command_min_x<min_x || min_x == 0.0
|
32
32
|
|
33
|
-
|
34
|
-
|
35
|
-
end
|
36
|
-
end
|
33
|
+
command_min_y = [command.p0y, command.p1y].min
|
34
|
+
min_y = command_min_y if !min_y || command_min_y<min_y || min_y == 0.0
|
37
35
|
end
|
38
36
|
return min_x, min_y
|
39
37
|
end
|
40
38
|
|
39
|
+
def self.get_max_x_y(svg_commands)
|
40
|
+
max_x = nil
|
41
|
+
max_y = nil
|
42
|
+
|
43
|
+
svg_commands.map do |command|
|
44
|
+
command_max_x = [command.p0x, command.p1x].max
|
45
|
+
max_x = command_max_x if !max_x || command_max_x>max_x || max_x == 0.0
|
46
|
+
|
47
|
+
command_max_y = [command.p0y, command.p1y].max
|
48
|
+
max_y = command_max_y if !max_y || command_max_y>max_y || max_y == 0.0
|
49
|
+
end
|
50
|
+
return max_x, max_y
|
51
|
+
end
|
52
|
+
|
41
53
|
def self.add_margin_to_svg_commands(svg_commands, min_x, min_y, buffer=20.0)
|
54
|
+
x_margin = buffer-min_x
|
55
|
+
y_margin = buffer-min_y
|
56
|
+
|
42
57
|
svg_commands.map do |command|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
58
|
+
command.add_margins(x_margin, y_margin)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def self.sort_commands_ascending_by_x(svg_commands)
|
63
|
+
svg_commands.sort do |a,b|
|
64
|
+
a.first.p0x <=> b.first.p0x
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def self.add_moves_back_to_svg_commands(svg_commands)
|
69
|
+
commands_with_moves = svg_commands.map do |boxes|
|
70
|
+
boxes.map do |commands|
|
71
|
+
move_to_command = SVGCommand.new(
|
72
|
+
type: ConversionConstants::MOVE,
|
73
|
+
p1x: commands.first.p0x,
|
74
|
+
p1y: commands.first.p0y
|
75
|
+
)
|
76
|
+
[move_to_command, commands.flatten]
|
51
77
|
end
|
52
|
-
end
|
53
|
-
buffered_command
|
54
78
|
end
|
79
|
+
commands_with_moves.flatten
|
80
|
+
end
|
81
|
+
|
82
|
+
def self.group_commands_and_remove_moves(svg_commands)
|
83
|
+
svg_commands
|
84
|
+
.chunk { |cmd| cmd.type == 'M' }
|
85
|
+
.reject { |enum| enum[0] }
|
86
|
+
.map { |enum| enum[1] }
|
55
87
|
end
|
56
88
|
|
57
89
|
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'convert_svg_string_to_gcode/models/box'
|
2
|
+
require 'convert_svg_string_to_gcode/helpers/adjust_svg_commands_for_plotter'
|
3
|
+
|
4
|
+
class BoxHelper
|
5
|
+
|
6
|
+
def self.sort_commands_into_boxes(svg_commands, rows: 10, columns: 3)
|
7
|
+
|
8
|
+
boxes = create_write_boxes(svg_commands, rows, columns)
|
9
|
+
boxed_commands = boxes.map { |bc| [] }
|
10
|
+
|
11
|
+
box_order = []
|
12
|
+
|
13
|
+
boxes.each_slice(rows).with_index do |box_group, i|
|
14
|
+
if i.even?
|
15
|
+
box_order << box_group.map { |b| b.box_number }
|
16
|
+
else
|
17
|
+
box_order << box_group.reverse_each.map { |b| b.box_number }
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
box_order_index = {}
|
22
|
+
|
23
|
+
box_order.flatten.each.with_index do |order_number, i|
|
24
|
+
box_order_index[order_number] = i
|
25
|
+
end
|
26
|
+
|
27
|
+
svg_commands.each do |command|
|
28
|
+
box_order.flatten.each do |box_number|
|
29
|
+
next unless command_is_within_box?(command, boxes[box_number])
|
30
|
+
boxed_commands[box_order_index[box_number]] << command
|
31
|
+
end
|
32
|
+
end
|
33
|
+
boxed_commands
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.command_is_within_box?(command, box)
|
37
|
+
command.first.p0x.between?(box.x_min, box.x_max) &&
|
38
|
+
command.first.p0y.between?(box.y_min, box.y_max)
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.create_write_boxes(svg_commands, rows = 10, columns= 3)
|
42
|
+
x_max, y_max = AdjustSVGCommandsForPlotter.get_max_x_y(svg_commands.flatten)
|
43
|
+
x_step = x_max/columns
|
44
|
+
y_step = y_max/rows
|
45
|
+
|
46
|
+
x = 0
|
47
|
+
y = 0
|
48
|
+
boxes = []
|
49
|
+
|
50
|
+
columns.times do |c|
|
51
|
+
x_min = x
|
52
|
+
x_max = x+x_step
|
53
|
+
x = x+x_step
|
54
|
+
|
55
|
+
rows.times do |r|
|
56
|
+
y_min = y
|
57
|
+
y_max = y+y_step
|
58
|
+
y = y+y_step
|
59
|
+
|
60
|
+
boxes << Box.new(
|
61
|
+
box_number:rows*c+r,
|
62
|
+
x_min: x_min,
|
63
|
+
x_max: x_max,
|
64
|
+
y_min: y_min,
|
65
|
+
y_max: y_max
|
66
|
+
)
|
67
|
+
end
|
68
|
+
y=0
|
69
|
+
end
|
70
|
+
boxes
|
71
|
+
end
|
72
|
+
|
73
|
+
private_class_method :create_write_boxes
|
74
|
+
|
75
|
+
end
|
@@ -1,28 +1,56 @@
|
|
1
|
+
require 'convert_svg_string_to_gcode/models/svg_command'
|
1
2
|
|
2
3
|
class CreateCommandsFromTokens
|
3
4
|
def self.perform(svg_tokens)
|
5
|
+
last_command = SVGCommand.new(
|
6
|
+
type: ConversionConstants::MOVE,
|
7
|
+
p1x: 0.0,
|
8
|
+
p1y: 0.0,
|
9
|
+
p0x: 0.0,
|
10
|
+
p0y: 0.0,
|
11
|
+
p1x: 0.0,
|
12
|
+
p1y: 0.0
|
13
|
+
)
|
14
|
+
|
4
15
|
svg_commands = svg_tokens.each_with_index.map do |token, i|
|
5
|
-
svg_command=nil
|
16
|
+
svg_command = nil
|
17
|
+
|
6
18
|
if token.match(%r{[#{ConversionConstants::GCODE_COMMANDS}]})
|
7
19
|
case token
|
8
20
|
when ConversionConstants::MOVE
|
9
|
-
svg_command =
|
21
|
+
svg_command = SVGCommand.new(
|
22
|
+
type: ConversionConstants::MOVE,
|
23
|
+
p0x: last_command.p1x,
|
24
|
+
p0y: last_command.p1y,
|
25
|
+
p1x: svg_tokens[i+1],
|
26
|
+
p1y: svg_tokens[i+2]
|
27
|
+
)
|
10
28
|
when ConversionConstants::LINE_TO
|
11
|
-
svg_command =
|
29
|
+
svg_command = SVGCommand.new(
|
30
|
+
type: ConversionConstants::LINE_TO,
|
31
|
+
p0x: last_command.p1x,
|
32
|
+
p0y: last_command.p1y,
|
33
|
+
p1x: svg_tokens[i+1],
|
34
|
+
p1y: svg_tokens[i+2]
|
35
|
+
)
|
12
36
|
when ConversionConstants::CURVE
|
13
|
-
svg_command =
|
14
|
-
|
37
|
+
svg_command = SVGCommand.new(
|
38
|
+
type: ConversionConstants::CURVE,
|
39
|
+
p0x: last_command.p1x,
|
40
|
+
p0y: last_command.p1y,
|
15
41
|
cp0x: svg_tokens[i+1],
|
16
42
|
cp0y: svg_tokens[i+2],
|
17
43
|
cp1x: svg_tokens[i+3],
|
18
44
|
cp1y: svg_tokens[i+4],
|
19
45
|
p1x: svg_tokens[i+5],
|
20
46
|
p1y: svg_tokens[i+6]
|
21
|
-
|
47
|
+
)
|
22
48
|
end
|
23
49
|
end
|
50
|
+
last_command = svg_command if svg_command
|
24
51
|
svg_command
|
25
52
|
end
|
26
53
|
svg_commands.compact
|
27
54
|
end
|
55
|
+
|
28
56
|
end
|
@@ -1,48 +1,47 @@
|
|
1
|
-
|
1
|
+
require 'convert_svg_string_to_gcode/constants/plotter_config'
|
2
2
|
class CreateGCodeArrayFromSVGCommands
|
3
3
|
def self.perform(commands, options = {step: 0.20})
|
4
4
|
start_point = nil
|
5
5
|
step=options[:step]
|
6
6
|
|
7
7
|
gcode_array = commands.map do |c|
|
8
|
-
case c
|
8
|
+
case c.type
|
9
9
|
when ConversionConstants::MOVE
|
10
|
-
|
10
|
+
move_to_point(c)
|
11
11
|
when ConversionConstants::LINE_TO
|
12
|
-
|
12
|
+
draw_to_point(c)
|
13
13
|
when ConversionConstants::CURVE
|
14
|
-
|
14
|
+
create_gcode_path_from_bezier(c, step)
|
15
15
|
else
|
16
16
|
throw Error
|
17
17
|
end
|
18
|
-
command_array
|
19
18
|
end
|
20
19
|
end
|
21
20
|
|
22
21
|
def self.move_to_point(new_point)
|
23
|
-
x_value = new_point
|
24
|
-
y_value = new_point
|
25
|
-
command = ["G0 X#{x_value} Y#{y_value} #{
|
26
|
-
return command
|
22
|
+
x_value = new_point.p1x
|
23
|
+
y_value = new_point.p1y
|
24
|
+
command = ["G0 X#{x_value} Y#{y_value} #{PlotterConfig::Z_UP}"]
|
25
|
+
return command
|
27
26
|
end
|
28
27
|
|
29
28
|
def self.draw_to_point(new_point)
|
30
|
-
x_value = new_point
|
31
|
-
y_value = new_point
|
32
|
-
command = ["G1 X#{x_value} Y#{y_value} #{
|
33
|
-
return command
|
29
|
+
x_value = new_point.p1x
|
30
|
+
y_value = new_point.p1y
|
31
|
+
command = ["G1 X#{x_value} Y#{y_value} #{PlotterConfig::Z_DOWN}"]
|
32
|
+
return command
|
34
33
|
end
|
35
34
|
|
36
|
-
def self.create_gcode_path_from_bezier(
|
35
|
+
def self.create_gcode_path_from_bezier(svg_command, step)
|
37
36
|
|
38
|
-
p0x =
|
39
|
-
p0y =
|
40
|
-
cp0x = svg_command
|
41
|
-
cp0y = svg_command
|
42
|
-
cp1x = svg_command
|
43
|
-
cp1y = svg_command
|
44
|
-
p1x = svg_command
|
45
|
-
p1y = svg_command
|
37
|
+
p0x = svg_command.p0x
|
38
|
+
p0y = svg_command.p0y
|
39
|
+
cp0x = svg_command.cp0x
|
40
|
+
cp0y = svg_command.cp0y
|
41
|
+
cp1x = svg_command.cp1x
|
42
|
+
cp1y = svg_command.cp1y
|
43
|
+
p1x = svg_command.p1x
|
44
|
+
p1y = svg_command.p1y
|
46
45
|
|
47
46
|
t = step
|
48
47
|
|
@@ -63,10 +62,10 @@ class CreateGCodeArrayFromSVGCommands
|
|
63
62
|
|
64
63
|
new_point_x = ( (1 - t) * dx ) + (t * ex)
|
65
64
|
new_point_y = ( (1 - t) * dy ) + (t * ey)
|
66
|
-
gcode_array << "G1 X#{new_point_x} Y#{new_point_y}
|
65
|
+
gcode_array << "G1 X#{new_point_x} Y#{new_point_y} #{PlotterConfig::Z_DOWN}"
|
67
66
|
t+=step
|
68
67
|
end
|
69
|
-
return gcode_array
|
68
|
+
return gcode_array
|
70
69
|
end
|
71
70
|
|
72
71
|
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
class SVGCommand
|
2
|
+
attr_accessor :type
|
3
|
+
def initialize(**params)
|
4
|
+
@type = params[:type]
|
5
|
+
@points = params.each_with_object({}) do |(param, value), hsh|
|
6
|
+
unless ConversionConstants::VALID_CMD_ATTRIBUTES.include?(param)
|
7
|
+
raise TypeError.new('Point label not defined')
|
8
|
+
end
|
9
|
+
hsh[param] = Float(value) unless value == nil || param == ConversionConstants::TYPE_LABEL
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def method_missing(name)
|
14
|
+
super unless ConversionConstants::VALID_CMD_ATTRIBUTES.include? name
|
15
|
+
value = @points[name]
|
16
|
+
return value
|
17
|
+
end
|
18
|
+
|
19
|
+
def adjust_by_proportion(proportion)
|
20
|
+
mutated_cp0x = self.cp0x*proportion if self.cp0x
|
21
|
+
mutated_cp0y = self.cp0y*proportion if self.cp0y
|
22
|
+
mutated_cp1x = self.cp1x*proportion if self.cp1x
|
23
|
+
mutated_cp1y = self.cp1y*proportion if self.cp1y
|
24
|
+
mutated_p0x = self.p0x*proportion if self.p0x
|
25
|
+
mutated_p0y = self.p0y*proportion if self.p0y
|
26
|
+
mutated_p1x = self.p1x*proportion if self.p1x
|
27
|
+
mutated_p1y = self.p1y*proportion if self.p1y
|
28
|
+
|
29
|
+
SVGCommand.new(
|
30
|
+
type: @type,
|
31
|
+
cp0x: mutated_cp0x,
|
32
|
+
cp0y: mutated_cp0y,
|
33
|
+
cp1x: mutated_cp1x,
|
34
|
+
cp1y: mutated_cp1y,
|
35
|
+
p0x: mutated_p0x,
|
36
|
+
p0y: mutated_p0y,
|
37
|
+
p1x: mutated_p1x,
|
38
|
+
p1y: mutated_p1y
|
39
|
+
)
|
40
|
+
end
|
41
|
+
|
42
|
+
def add_margins(x_margin, y_margin)
|
43
|
+
mutated_cp0x = self.cp0x+x_margin if self.cp0x
|
44
|
+
mutated_cp0y = self.cp0y+y_margin if self.cp0y
|
45
|
+
mutated_cp1x = self.cp1x+x_margin if self.cp1x
|
46
|
+
mutated_cp1y = self.cp1y+y_margin if self.cp1y
|
47
|
+
mutated_p0x = self.p0x+x_margin if self.p0x
|
48
|
+
mutated_p0y = self.p0y+y_margin if self.p0y
|
49
|
+
mutated_p1x = self.p1x+x_margin if self.p1x
|
50
|
+
mutated_p1y = self.p1y+y_margin if self.p1y
|
51
|
+
|
52
|
+
SVGCommand.new(
|
53
|
+
type: @type,
|
54
|
+
p0x: mutated_p0x,
|
55
|
+
p0y: mutated_p0y,
|
56
|
+
p1x: mutated_p1x,
|
57
|
+
p1y: mutated_p1y,
|
58
|
+
cp0x: mutated_cp0x,
|
59
|
+
cp0y: mutated_cp0y,
|
60
|
+
cp1x: mutated_cp1x,
|
61
|
+
cp1y: mutated_cp1y,
|
62
|
+
)
|
63
|
+
end
|
64
|
+
end
|
data/script/console
ADDED
data/script/test
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'convert_svg_string_to_gcode/helpers/parse_svg_string'
|
2
|
+
require 'convert_svg_string_to_gcode/helpers/tokenize_parsed_svg'
|
3
|
+
require 'convert_svg_string_to_gcode/helpers/create_commands_from_tokens'
|
4
|
+
require 'convert_svg_string_to_gcode/helpers/adjust_svg_commands_for_plotter'
|
5
|
+
require 'convert_svg_string_to_gcode/helpers/create_gcode_array_from_svg_commands'
|
6
|
+
require 'convert_svg_string_to_gcode/helpers/create_gcode_from_gcode_array'
|
7
|
+
require 'fixtures/spec_constants'
|
8
|
+
|
9
|
+
class FactoryHelper
|
10
|
+
def self.parsed_svg
|
11
|
+
ParseSVGString.perform(SpecConstants::TEST_SVG_AS_STRING)
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.svg_tokens
|
15
|
+
TokenizeParsedSVG.perform(parsed_svg)
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.svg_commands
|
19
|
+
CreateCommandsFromTokens.perform(svg_tokens)
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.adjusted_svg_commands
|
23
|
+
AdjustSVGCommandsForPlotter.perform(svg_commands, ConversionConstants::PROPORTION )
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.gcode_array
|
27
|
+
CreateGCodeArrayFromSVGCommands.perform(adjusted_svg_commands)
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'convert_svg_string_to_gcode/models/svg_command'
|
2
|
+
require 'convert_svg_string_to_gcode/constants/conversion_constants'
|
3
|
+
|
4
|
+
class SpecConstants
|
5
|
+
TEST_SVG_AS_STRING = "<?xml version=\"1.0\" standalone=\"yes\"?>\n<svg width=\"6375\" height=\"4781\">\n<path style=\"stroke:#020202; stroke-linecap: round; stroke-width:5;fill:none;\" d=\"M524 313C537.472 324.483 557.635 339.142 575 343.649\"/>\n</svg>\n"
|
6
|
+
TEST_SVG_TOKENS = [ConversionConstants::MOVE, "524", "313", "C", "537.472",
|
7
|
+
"324.483", "557.635", "339.142", "575", "343.649"]
|
8
|
+
TEST_SVG_COMMANDS = [SVGCommand.new(type:"M", p0x:0.0, p0y:0.0, p1x:"524", p1y:"313"),SVGCommand.new(type:"C", p0x: "524", p0y:"313", cp0x: "537.472", cp0y: "324.483", cp1x: "557.635", cp1y: "339.142", p1x:"575", p1y:"343.649")]
|
9
|
+
TEST_ADJUSTED_COMMANDS = [SVGCommand.new(type: "M", p1x: 20.0, p1y:20.0), SVGCommand.new(type:"C", p0x:20.0, p0y:20.0, cp0x:29.43040000000002, cp0y:28.038099999999986, cp1x:43.54450000000003, cp1y:38.29939999999999, p1x:55.700000000000045, p1y:41.45429999999999)]
|
10
|
+
|
11
|
+
TEST_GCODE_ARRAY = [["G0 X20.0 Y20.0 Z30.0"], ["G1 X26.167145600000012 Y25.015007199999996 Z10.0", "G1 X33.13954880000002 Y30.115761599999992 Z10.0", "G1 X40.59837920000004 Y34.85444239999999 Z10.0", "G1 X48.224806400000034 Y38.78322879999999 Z10.0"]]
|
12
|
+
|
13
|
+
EXPECTED_GCODE_TEST_SVG_OUTPUT = "%\nG21\nG00 Z30.0\nG00 X0.0 Y0.0\nG0 X20.0 Y20.0 Z30.0\nG1 X26.167145600000012 Y25.015007199999996 Z10.0\nG1 X33.13954880000002 Y30.115761599999992 Z10.0\nG1 X40.59837920000004 Y34.85444239999999 Z10.0\nG1 X48.224806400000034 Y38.78322879999999 Z10.0\nG00 X0.0 Y0.0 Z30.0\n%"
|
14
|
+
|
15
|
+
TEST_IMAGE_LOCATION = "https://res.cloudinary.com/trunk-club/image/upload/v1456519728/original_note.jpg"
|
16
|
+
end
|
data/spec/helpers.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
module Helpers
|
2
|
+
|
3
|
+
def now
|
4
|
+
Time.parse("2013-01-01T00:00:00Z")
|
5
|
+
end
|
6
|
+
|
7
|
+
def stubs_time
|
8
|
+
allow(Time).to receive(:now).and_return(now)
|
9
|
+
end
|
10
|
+
|
11
|
+
def client
|
12
|
+
api_client
|
13
|
+
end
|
14
|
+
|
15
|
+
def api_client
|
16
|
+
# Fail if the clients receive unexpected messages, stubbing is expected in specs
|
17
|
+
@client ||= double
|
18
|
+
end
|
19
|
+
|
20
|
+
def build_response(payload, status=200)
|
21
|
+
double(status: status, body: payload.to_json)
|
22
|
+
end
|
23
|
+
|
24
|
+
def service_fails_unexpectedly(http_verb, error_payload={message: "Oh snap!"})
|
25
|
+
allow(client).to receive(http_verb).and_return(build_response(error_payload, 500))
|
26
|
+
end
|
27
|
+
|
28
|
+
def last_json
|
29
|
+
last_response.body
|
30
|
+
end
|
31
|
+
|
32
|
+
def response_payload
|
33
|
+
JSON.parse(last_json)
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
ENV['RACK_ENV'] = 'test'
|
2
|
+
|
3
|
+
require 'rspec'
|
4
|
+
require 'rack/test'
|
5
|
+
require 'database_cleaner'
|
6
|
+
require_relative 'helpers'
|
7
|
+
require 'fixtures/spec_constants'
|
8
|
+
|
9
|
+
RSpec.configure do |config|
|
10
|
+
config.include(Helpers)
|
11
|
+
|
12
|
+
# Raise errors for deprecated rspec syntax
|
13
|
+
config.raise_errors_for_deprecations!
|
14
|
+
|
15
|
+
# Colored tests are more _exciting_
|
16
|
+
config.color = true
|
17
|
+
|
18
|
+
# Set the order to random unless we pass it in from the command line
|
19
|
+
config.order = :rand unless ARGV.any? { |arg| %w(--order --seed).include?(arg) }
|
20
|
+
|
21
|
+
# Define DatabaseCleaner strategy
|
22
|
+
# -------------------------------------------
|
23
|
+
# config.before(:suite) do
|
24
|
+
# DatabaseCleaner[:active_record].strategy = :transaction
|
25
|
+
# DatabaseCleaner.clean_with(:truncation)
|
26
|
+
# end
|
27
|
+
|
28
|
+
# Wire up DatabaseCleaner before and after each example
|
29
|
+
# -------------------------------------------
|
30
|
+
# config.around(:each) do |example|
|
31
|
+
# DatabaseCleaner.cleaning do
|
32
|
+
# example.run
|
33
|
+
# end
|
34
|
+
# end
|
35
|
+
|
36
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'convert_svg_string_to_gcode/helpers/adjust_svg_commands_for_plotter'
|
2
|
+
require 'spec_helper'
|
3
|
+
require 'factory_helper'
|
4
|
+
|
5
|
+
RSpec.describe AdjustSVGCommandsForPlotter do
|
6
|
+
let(:svg_commands) { FactoryHelper.svg_commands }
|
7
|
+
let(:spec_adjusted_commands) { SpecConstants::TEST_ADJUSTED_COMMANDS }
|
8
|
+
|
9
|
+
it 'adjusts SVG commands for the plotter' do
|
10
|
+
adjusted_svg_commands = AdjustSVGCommandsForPlotter.perform(svg_commands, ConversionConstants::PROPORTION)
|
11
|
+
|
12
|
+
expect(adjusted_svg_commands.first.p1x).to eq(spec_adjusted_commands.first.p1x)
|
13
|
+
expect(adjusted_svg_commands.first.p1y).to eq(spec_adjusted_commands.first.p1y)
|
14
|
+
|
15
|
+
expect(adjusted_svg_commands.second.cp0x).to eq(spec_adjusted_commands.second.cp0x)
|
16
|
+
expect(adjusted_svg_commands.second.cp0y).to eq(spec_adjusted_commands.second.cp0y)
|
17
|
+
expect(adjusted_svg_commands.second.cp1x).to eq(spec_adjusted_commands.second.cp1x)
|
18
|
+
expect(adjusted_svg_commands.second.cp1y).to eq(spec_adjusted_commands.second.cp1y)
|
19
|
+
expect(adjusted_svg_commands.second.p0x).to eq(spec_adjusted_commands.second.p0x)
|
20
|
+
expect(adjusted_svg_commands.second.p0y).to eq(spec_adjusted_commands.second.p0y)
|
21
|
+
expect(adjusted_svg_commands.second.p1x).to eq(spec_adjusted_commands.second.p1x)
|
22
|
+
expect(adjusted_svg_commands.second.p1y).to eq(spec_adjusted_commands.second.p1y)
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'convert_svg_string_to_gcode'
|
3
|
+
require 'convert_svg_string_to_gcode/helpers/parse_svg_string'
|
4
|
+
require 'convert_svg_string_to_gcode/helpers/tokenize_parsed_svg'
|
5
|
+
|
6
|
+
RSpec.describe ConvertSVGStringToGCode do
|
7
|
+
let(:svg_as_string) { SpecConstants::TEST_SVG_AS_STRING }
|
8
|
+
|
9
|
+
it 'converts SVG string into G-Code' do
|
10
|
+
gcode = ConvertSVGStringToGCode.perform(svg_as_string)
|
11
|
+
expect(gcode).to eq(SpecConstants::EXPECTED_GCODE_TEST_SVG_OUTPUT)
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'active_support'
|
2
|
+
require 'active_support/core_ext'
|
3
|
+
require 'convert_svg_string_to_gcode/helpers/create_commands_from_tokens'
|
4
|
+
require 'factory_helper'
|
5
|
+
|
6
|
+
RSpec.describe CreateCommandsFromTokens do
|
7
|
+
let(:svg_tokens) { SpecConstants::TEST_SVG_TOKENS }
|
8
|
+
let(:spec_commands) { SpecConstants::TEST_SVG_COMMANDS }
|
9
|
+
|
10
|
+
it 'creates command array from tokens' do
|
11
|
+
commands = CreateCommandsFromTokens.perform(svg_tokens)
|
12
|
+
|
13
|
+
expect(spec_commands.first.p1x).to eq(spec_commands.first.p1x)
|
14
|
+
expect(spec_commands.first.p1y).to eq(spec_commands.first.p1y)
|
15
|
+
|
16
|
+
expect(spec_commands.second.cp0x).to eq(spec_commands.second.cp0x)
|
17
|
+
expect(spec_commands.second.cp0y).to eq(spec_commands.second.cp0y)
|
18
|
+
expect(spec_commands.second.cp1x).to eq(spec_commands.second.cp1x)
|
19
|
+
expect(spec_commands.second.cp1y).to eq(spec_commands.second.cp1y)
|
20
|
+
expect(spec_commands.second.p0x).to eq(spec_commands.second.p0x)
|
21
|
+
expect(spec_commands.second.p0y).to eq(spec_commands.second.p0y)
|
22
|
+
expect(spec_commands.second.p1x).to eq(spec_commands.second.p1x)
|
23
|
+
expect(spec_commands.second.p1y).to eq(spec_commands.second.p1y)
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'convert_svg_string_to_gcode/helpers/create_gcode_array_from_svg_commands'
|
2
|
+
require 'spec_helper'
|
3
|
+
require 'factory_helper'
|
4
|
+
|
5
|
+
RSpec.describe CreateGCodeArrayFromSVGCommands do
|
6
|
+
let(:adjusted_svg_commands) { FactoryHelper.adjusted_svg_commands }
|
7
|
+
|
8
|
+
it 'creates a G-Code array from SVG commands' do
|
9
|
+
gcode_array = CreateGCodeArrayFromSVGCommands.perform(adjusted_svg_commands)
|
10
|
+
expect(gcode_array).to eq(SpecConstants::TEST_GCODE_ARRAY)
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'factory_helper'
|
3
|
+
require 'convert_svg_string_to_gcode/helpers/create_gcode_from_gcode_array'
|
4
|
+
|
5
|
+
|
6
|
+
RSpec.describe CreateGCodeFromGCodeArray do
|
7
|
+
let(:gcode_array) { FactoryHelper.gcode_array }
|
8
|
+
|
9
|
+
it 'converts G-Code Array to G-Code' do
|
10
|
+
gcode = CreateGCodeFromGCodeArray.perform(gcode_array)
|
11
|
+
expect(gcode).to eq(SpecConstants::EXPECTED_GCODE_TEST_SVG_OUTPUT)
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'convert_svg_string_to_gcode/helpers/read_svg_to_string'
|
3
|
+
|
4
|
+
RSpec.describe ReadSVGToString do
|
5
|
+
let(:svg_file) { File.open('spec/fixtures/test.svg') }
|
6
|
+
|
7
|
+
it 'reads in an SVG file and outputs a string' do
|
8
|
+
svg_as_string = ReadSVGToString.perform(svg_file)
|
9
|
+
expect(svg_as_string).to eq(SpecConstants::TEST_SVG_AS_STRING)
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'convert_svg_string_to_gcode/helpers/tokenize_parsed_svg'
|
2
|
+
require 'factory_helper'
|
3
|
+
|
4
|
+
RSpec.describe TokenizeParsedSVG do
|
5
|
+
let(:parsed_svg) { FactoryHelper.parsed_svg }
|
6
|
+
|
7
|
+
it 'takes a parsed SVG and returns tokens' do
|
8
|
+
svg_tokens = TokenizeParsedSVG.perform(parsed_svg)
|
9
|
+
expect(svg_tokens).to eq(SpecConstants::TEST_SVG_TOKENS)
|
10
|
+
end
|
11
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: convert_svg_string_to_gcode
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jesse Furmanek
|
@@ -16,15 +16,40 @@ executables: []
|
|
16
16
|
extensions: []
|
17
17
|
extra_rdoc_files: []
|
18
18
|
files:
|
19
|
+
- ".gitignore"
|
20
|
+
- Gemfile
|
21
|
+
- Gemfile.lock
|
22
|
+
- config/console.rb
|
23
|
+
- convert_svg_string_to_gcode-0.0.0.gem
|
19
24
|
- convert_svg_string_to_gcode.gemspec
|
20
25
|
- lib/convert_svg_string_to_gcode.rb
|
21
26
|
- lib/convert_svg_string_to_gcode/constants/conversion_constants.rb
|
27
|
+
- lib/convert_svg_string_to_gcode/constants/plotter_config.rb
|
22
28
|
- lib/convert_svg_string_to_gcode/helpers/adjust_svg_commands_for_plotter.rb
|
29
|
+
- lib/convert_svg_string_to_gcode/helpers/box_helper.rb
|
23
30
|
- lib/convert_svg_string_to_gcode/helpers/create_commands_from_tokens.rb
|
24
31
|
- lib/convert_svg_string_to_gcode/helpers/create_gcode_array_from_svg_commands.rb
|
25
32
|
- lib/convert_svg_string_to_gcode/helpers/create_gcode_from_gcode_array.rb
|
26
33
|
- lib/convert_svg_string_to_gcode/helpers/parse_svg_string.rb
|
34
|
+
- lib/convert_svg_string_to_gcode/helpers/read_svg_to_string.rb
|
27
35
|
- lib/convert_svg_string_to_gcode/helpers/tokenize_parsed_svg.rb
|
36
|
+
- lib/convert_svg_string_to_gcode/models/box.rb
|
37
|
+
- lib/convert_svg_string_to_gcode/models/svg_command.rb
|
38
|
+
- script/console
|
39
|
+
- script/test
|
40
|
+
- spec/factory_helper.rb
|
41
|
+
- spec/fixtures/spec_constants.rb
|
42
|
+
- spec/fixtures/test.svg
|
43
|
+
- spec/helpers.rb
|
44
|
+
- spec/spec_helper.rb
|
45
|
+
- spec/unit/adjust_svg_commands_for_plotter_spec.rb
|
46
|
+
- spec/unit/convert_svg_string_to_gcode_spec.rb
|
47
|
+
- spec/unit/create_commands_from_token_spec.rb
|
48
|
+
- spec/unit/create_gcode_array_from_svg_commands_spec.rb
|
49
|
+
- spec/unit/create_gcode_from_gcode_array_spec.rb
|
50
|
+
- spec/unit/parse_svg_string_spec.rb
|
51
|
+
- spec/unit/read_svg_to_string_spec.rb
|
52
|
+
- spec/unit/tokenize_parsed_svg_spec.rb
|
28
53
|
homepage: http://rubygems.org/gems/svg_path_to_gcode
|
29
54
|
licenses:
|
30
55
|
- MIT
|