svgcode 0.4.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4d486f6eb402ed92018dc7ecf6ce1bfcbb714df2
4
- data.tar.gz: 2795cf35e94a4a7a3e4d925fa8c89660a2cfd015
3
+ metadata.gz: 85836f130f6ff7d82e701ed3794699d34a93e6c6
4
+ data.tar.gz: a3ade6019d2663505e5ca24d20b62f63c80efb02
5
5
  SHA512:
6
- metadata.gz: 20beaceac4a88028c7bdffa5af0b1d5bebe85e18cd1a1a17cf4714080c28ba36d2d454cbca484f76371a4bb1a01e61c9e08a3831e02a45f9fdc08c5e51fdcdc2
7
- data.tar.gz: 1af5a856a2cabfb9dac1c4e3f142aad744a8717ef1341a431b712024848ac71012f7d5a8f62dd47c1cc6961d35b610e9904c12aff33f1ff6ae58b19ffe82c580
6
+ metadata.gz: 51b98e6d618d94e0e0211872f1aff91a6b281e41b44abbbc8b42b3f9bda9ec3c13908ec1f0140950ee815df1340e15fb65fed7ffee3e6d0816c410feba69e661
7
+ data.tar.gz: 5447772034b322ba08006c6d0108c587a8c0d0e9dccdc5a58f4df96367c16472adc9cc103da202db94d22602a057e47b01a8738f949b8e0607b2f6775175d812
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- svgcode (0.4.0)
4
+ svgcode (0.6.0)
5
5
  nokogiri (~> 1.8)
6
6
  thor (~> 0.20)
7
7
 
@@ -9,11 +9,43 @@ GEM
9
9
  remote: https://rubygems.org/
10
10
  specs:
11
11
  byebug (9.1.0)
12
+ coderay (1.1.2)
12
13
  diff-lcs (1.3)
14
+ ffi (1.9.23)
15
+ formatador (0.2.5)
16
+ guard (2.14.2)
17
+ formatador (>= 0.2.4)
18
+ listen (>= 2.7, < 4.0)
19
+ lumberjack (>= 1.0.12, < 2.0)
20
+ nenv (~> 0.1)
21
+ notiffany (~> 0.0)
22
+ pry (>= 0.9.12)
23
+ shellany (~> 0.0)
24
+ thor (>= 0.18.1)
25
+ guard-compat (1.2.1)
26
+ guard-shell (0.7.1)
27
+ guard (>= 2.0.0)
28
+ guard-compat (~> 1.0)
29
+ listen (3.1.5)
30
+ rb-fsevent (~> 0.9, >= 0.9.4)
31
+ rb-inotify (~> 0.9, >= 0.9.7)
32
+ ruby_dep (~> 1.2)
33
+ lumberjack (1.0.13)
34
+ method_source (0.9.0)
13
35
  mini_portile2 (2.3.0)
36
+ nenv (0.3.0)
14
37
  nokogiri (1.8.2)
15
38
  mini_portile2 (~> 2.3.0)
39
+ notiffany (0.1.1)
40
+ nenv (~> 0.1)
41
+ shellany (~> 0.0)
42
+ pry (0.11.3)
43
+ coderay (~> 1.1.0)
44
+ method_source (~> 0.9.0)
16
45
  rake (10.5.0)
46
+ rb-fsevent (0.10.3)
47
+ rb-inotify (0.9.10)
48
+ ffi (>= 0.5.0, < 2)
17
49
  rspec (3.7.0)
18
50
  rspec-core (~> 3.7.0)
19
51
  rspec-expectations (~> 3.7.0)
@@ -27,6 +59,8 @@ GEM
27
59
  diff-lcs (>= 1.2.0, < 2.0)
28
60
  rspec-support (~> 3.7.0)
29
61
  rspec-support (3.7.0)
62
+ ruby_dep (1.5.0)
63
+ shellany (0.0.1)
30
64
  thor (0.20.0)
31
65
  yard (0.9.12)
32
66
 
@@ -36,6 +70,8 @@ PLATFORMS
36
70
  DEPENDENCIES
37
71
  bundler (~> 1.16)
38
72
  byebug
73
+ guard
74
+ guard-shell
39
75
  rake (~> 10.0)
40
76
  rspec (~> 3.0)
41
77
  svgcode!
@@ -0,0 +1,16 @@
1
+ require 'svgcode/cli'
2
+ require 'tempfile'
3
+
4
+ guard :shell do
5
+ watch(//) do |mod|
6
+ ngc_file = Tempfile.new
7
+ cli = Svgcode::CLI.new
8
+
9
+ cli.invoke('parse', ['~/Desktop/azabache.svg'],
10
+ out_path: ngc_file.path,
11
+ comments: true
12
+ )
13
+
14
+ cli.invoke('post', [ngc_file.path])
15
+ end
16
+ end
data/TODO.md CHANGED
@@ -15,7 +15,5 @@
15
15
  - optionally print GCode desciptions
16
16
  - write docs
17
17
  - optimise cut order
18
- - better end to end tests
19
- - maybe include LinuxCNC
20
18
  - cut to depth in multiple passes
21
19
  - v-engrave filled areas
@@ -1,43 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  require 'bundler/setup'
4
- require 'svgcode'
5
- require 'thor'
4
+ require 'svgcode/cli'
6
5
 
7
-
8
- class SVGCLI < Thor
9
- desc 'parse SVG_PATH [--out OUT_PATH] [--comments]',
10
- 'parses an SVG file to a G-code file'
11
- option :out_path
12
- option :comments, type: :boolean
13
- long_desc <<-LONGDESC
14
- `svgcode parse ~/Desktop/img.svg` will save the G-code file as
15
- '~/Desktop/img.ngc'.
16
-
17
- Optionally set the --out-path flag to save the G-code file elsewhere
18
- \x5 e.g. `svgcode parse ~/Documents/img.svg --out-path ~/Desktop/gcode.nc`
19
-
20
- Optionally pass the --comments flag to print SVG IDs as comments
21
- \x5 e.g. `svgcode parse --comments ~/Desktop/img.svg`
22
- LONGDESC
23
- def parse(in_path)
24
- in_path = File.expand_path(in_path)
25
- raise "#{in_path} is not readable" unless File.readable?(in_path)
26
- svg_str = File.read(in_path)
27
-
28
- out_path =
29
- if options[:out_path].nil?
30
- in_path.gsub(/\.svg\Z/i, '.ngc')
31
- else
32
- File.expand_path(options[:out_path])
33
- end
34
-
35
- opts = { comments: options[:comments] }
36
- File.open(out_path, 'w') { |f| f << Svgcode.parse(svg_str, opts) }
37
-
38
- puts "G-code written to #{out_path}"
39
- end
40
- end
41
-
42
-
43
- SVGCLI.start(ARGV)
6
+ Svgcode::CLI.start(ARGV)
@@ -1,3 +1,4 @@
1
+ require 'svgcode/utility'
1
2
  require 'svgcode/version'
2
3
  require 'svgcode/gcode/converter'
3
4
  require 'svgcode/svg/transform'
@@ -15,20 +16,24 @@ module Svgcode
15
16
  opts[:max_y] = view_box.split(/\s+/).last.to_f
16
17
  converter = Converter.new(opts)
17
18
 
18
- doc.xpath('//path').each do |path|
19
+ doc.xpath('//path|//circle').each do |el|
19
20
  if opts[:comments]
20
- ids = path.xpath('ancestor::g[@id]').collect do |t|
21
+ ids = el.xpath('ancestor::g[@id]').collect do |t|
21
22
  t.attributes['id'].value
22
23
  end
23
24
 
24
25
  converter.comment!(ids.join(' '))
25
26
  end
26
27
 
27
- converter.transforms = path.xpath('ancestor::g[@transform]').collect do |t|
28
+ converter.transforms = el.xpath('ancestor::g[@transform]').collect do |t|
28
29
  Transform.new(t.attributes['transform'].value)
29
30
  end
30
31
 
31
- converter << path.attributes['d'].value
32
+ if el.name == 'path'
33
+ converter << el.attributes['d'].value
34
+ else
35
+ converter << el
36
+ end
32
37
  end
33
38
 
34
39
  converter.finish
@@ -0,0 +1,76 @@
1
+ require 'svgcode'
2
+ require 'thor'
3
+ require 'net/http'
4
+
5
+ module Svgcode
6
+ class CLI < Thor
7
+ DEFAULT_POST_URL = 'http://linux-cnc.bmo:8080'
8
+ DEFAULT_POST_NAME = 'file'
9
+
10
+ desc 'parse SVG_PATH [--out OUT_PATH] [--comments]',
11
+ 'parses an SVG file to a G-code file'
12
+ option :out_path
13
+ option :comments, type: :boolean
14
+ long_desc <<-LONGDESC
15
+ `svgcode parse ~/Desktop/img.svg` will save the G-code file as
16
+ '~/Desktop/img.ngc'.
17
+
18
+ Optionally set the --out-path flag to save the G-code file elsewhere
19
+ \x5 e.g. `svgcode parse ~/Documents/img.svg --out-path ~/Desktop/gcode.nc`
20
+
21
+ Optionally pass the --comments flag to print SVG IDs as comments
22
+ \x5 e.g. `svgcode parse --comments ~/Desktop/img.svg`
23
+ LONGDESC
24
+ def parse(in_path)
25
+ in_path = File.expand_path(in_path)
26
+ raise "#{in_path} is not readable" unless File.readable?(in_path)
27
+ svg_str = File.read(in_path)
28
+
29
+ out_path =
30
+ if options[:out_path].nil?
31
+ in_path.gsub(/\.svg\Z/i, '.ngc')
32
+ else
33
+ File.expand_path(options[:out_path])
34
+ end
35
+
36
+ opts = { comments: options[:comments] }
37
+ File.open(out_path, 'w') { |f| f << Svgcode.parse(svg_str, opts) }
38
+
39
+ puts "G-code written to #{out_path}"
40
+ end
41
+
42
+ desc 'post NGC_PATH [--url URL] [--post-name POST_NAME]',
43
+ 'posts an GCode file to a server'
44
+ option :url, default: DEFAULT_POST_URL
45
+ option :post_name, default: DEFAULT_POST_NAME
46
+ long_desc <<-LONGDESC
47
+ `svgcode post ~/Desktop/img.ngc` will post the GCode file to
48
+ #{DEFAULT_POST_URL}.
49
+
50
+ Optionally set the --url flag to post the GCode file elsewhere
51
+ \x5 e.g. `svgcode post ~/Documents/img.ngc --url http://192.168.20.7:9999`
52
+
53
+ Optionally pass the --post-name flag to name the file field something other
54
+ than the default '#{DEFAULT_POST_NAME}'
55
+ \x5 e.g. `svgcode post --post-name svgfile`
56
+ LONGDESC
57
+ def post(ngc_path)
58
+ ngc_path = File.expand_path(ngc_path)
59
+ raise "#{ngc_path} is not readable" unless File.readable?(ngc_path)
60
+
61
+ uri = URI(options[:url])
62
+ request = Net::HTTP::Post.new(uri)
63
+ form_data = [[options[:post_name], File.open(ngc_path)]]
64
+ message = nil
65
+
66
+ request.set_form form_data, 'multipart/form-data'
67
+ response = Net::HTTP.start(uri.hostname, uri.port) do |http|
68
+ http.request(request)
69
+ end
70
+
71
+ puts response
72
+
73
+ puts "G-code posted to #{options[:url]}"
74
+ end
75
+ end
76
+ end
@@ -123,6 +123,15 @@ module Svgcode
123
123
  ])
124
124
  end
125
125
 
126
+ # X and Y are the endpoint, and I is the X offset of the centrepoint
127
+ def self.arc(x, y, i)
128
+ Command.new(:g, 2, [
129
+ Command.new(:x, x),
130
+ Command.new(:y, y),
131
+ Command.new(:i, i)
132
+ ])
133
+ end
134
+
126
135
  def self.clear(clearance)
127
136
  Command.new(:g, 0, [
128
137
  Command.new(:z, clearance)
@@ -1,4 +1,5 @@
1
1
  require 'svgcode/gcode/program'
2
+ require 'svgcode/svg/circle'
2
3
  require 'svgcode/svg/path'
3
4
 
4
5
  module Svgcode
@@ -21,39 +22,15 @@ module Svgcode
21
22
  @program.feedrate!
22
23
  end
23
24
 
24
- def <<(svg_d)
25
- svg_start = nil
26
- path = SVG::Path.new(svg_d)
27
- start = nil
28
-
29
- path.commands.each do |cmd|
30
- cmd.apply_transforms!(@transforms)
31
- cmd.absolute? ? cmd.flip_points_y!(@max_y) : cmd.negate_points_y!
32
-
33
- if metric?
34
- cmd.divide_points_by!(PX_PER_MM)
35
- else
36
- cmd.divide_points_by!(PX_PER_INCH)
37
- end
38
-
39
- if (cmd.name == :close || cmd.absolute?) && @program.relative?
40
- @program.absolute!
41
- elsif cmd.relative? && @program.absolute?
42
- @program.relative!
43
- end
44
-
45
- case cmd.name
46
- when :move
47
- start = cmd.relative? ? cmd.absolute(@program.pos) : cmd
48
- @program.go!(cmd.points.first.x, cmd.points.first.y)
49
- when :line
50
- @program.cut!(cmd.points.first.x, cmd.points.first.y)
51
- when :cubic
52
- cubic!(cmd)
53
- when :close
54
- @program.cut!(start.points.first.x, start.points.first.y)
55
- start = nil
56
- end
25
+ def <<(str_or_command)
26
+ @start = nil
27
+
28
+ if str_or_command.is_a?(String)
29
+ path = SVG::Path.new(str_or_command)
30
+ path.commands.each { |cmd| add_command(cmd)}
31
+ else
32
+ cmd = SVG::Circle.new(str_or_command)
33
+ add_command(cmd)
57
34
  end
58
35
  end
59
36
 
@@ -80,6 +57,39 @@ module Svgcode
80
57
 
81
58
  private
82
59
 
60
+ def add_command(cmd)
61
+ cmd.apply_transforms!(@transforms)
62
+ cmd.absolute? ? cmd.flip_points_y!(@max_y) : cmd.negate_points_y!
63
+
64
+ if metric?
65
+ cmd.divide_points_by!(PX_PER_MM)
66
+ else
67
+ cmd.divide_points_by!(PX_PER_INCH)
68
+ end
69
+
70
+ if cmd.name == :close || cmd.absolute?
71
+ @program.absolute!
72
+ elsif cmd.relative?
73
+ @program.relative!
74
+ end
75
+
76
+ case cmd.name
77
+ when :move
78
+ @start = cmd.relative? ? cmd.absolute(@program.pos) : cmd
79
+ @program.go!(cmd.points.first.x, cmd.points.first.y)
80
+ when :line
81
+ @program.cut!(cmd.points.first.x, cmd.points.first.y)
82
+ when :cubic
83
+ cubic!(cmd)
84
+ when :circle
85
+ @program.go!(cmd.start_x, cmd.centre_y)
86
+ @program.arc!(cmd.start_x, cmd.centre_y, cmd.radius)
87
+ when :close
88
+ @program.cut!(@start.points.first.x, @start.points.first.y)
89
+ @start = nil
90
+ end
91
+ end
92
+
83
93
  def cubic!(cmd)
84
94
  # A relative SVG cubic bezier has all control points relative to start.
85
95
  # G-code I&J are relative to start, and P&Q relative to end.
@@ -61,7 +61,7 @@ module Svgcode
61
61
 
62
62
  def <<(command)
63
63
  if !command.is_a?(String) &&
64
- (@x.nil? || @y.nil?) &&
64
+ (@x.nil? || @y.nil?) &&
65
65
  command.letter == 'G' &&
66
66
  command.number < 6 &&
67
67
  command != Command.relative &&
@@ -156,6 +156,10 @@ module Svgcode
156
156
  end
157
157
  end
158
158
 
159
+ def arc!(x, y, i)
160
+ self << Command.arc(x, y, i)
161
+ end
162
+
159
163
  def pos
160
164
  Svgcode::SVG::Point.new(@x, @y)
161
165
  end
@@ -0,0 +1,91 @@
1
+ require 'svgcode/svg/point'
2
+
3
+ module Svgcode
4
+ module SVG
5
+ class BaseCommand
6
+ attr_reader :name, :absolute, :points
7
+
8
+ NAMES = {
9
+ 'm' => :move,
10
+ 'l' => :line,
11
+ 'c' => :cubic,
12
+ 'z' => :close
13
+ }
14
+
15
+ def initialize(opts)
16
+ @name = opts[:name]
17
+ @absolute = !!opts[:absolute]
18
+ @points = opts[:points] || []
19
+ end
20
+
21
+ def absolute?
22
+ @absolute
23
+ end
24
+
25
+ def relative?
26
+ !@absolute
27
+ end
28
+
29
+ def absolute(pos)
30
+ points = @points.collect { |p| p + pos }
31
+ Command.new(name: @name, absolute: true, points: points)
32
+ end
33
+
34
+ def absolute!(pos)
35
+ if relative?
36
+ @points.collect! { |p| p + pos }
37
+ @absolute = true
38
+ end
39
+ end
40
+
41
+ def negate_points_y
42
+ points = @points.collect { |point| point.negate_y }
43
+ Command.new(name: @name, absolute: @absolute, points: points)
44
+ end
45
+
46
+ def negate_points_y!
47
+ @points.each { |point| point.negate_y! }
48
+ nil
49
+ end
50
+
51
+ def divide_points_by!(amount)
52
+ @points.each { |point| point.divide_by!(amount) }
53
+ nil
54
+ end
55
+
56
+ def flip_points_y!(max_y)
57
+ @points.each { |point| point.flip_y!(max_y) }
58
+ nil
59
+ end
60
+
61
+ def apply_transforms!(transforms)
62
+ unless transforms.empty?
63
+ transforms.reverse.each do |transform|
64
+ @points.collect! { |point| transform.apply(point) }
65
+ end
66
+ end
67
+ end
68
+
69
+ def name_str
70
+ Command.name_str(@name, absolute?)
71
+ end
72
+
73
+ def ==(other)
74
+ other.is_a?(self.class) &&
75
+ other.name == @name &&
76
+ other.absolute? == @absolute &&
77
+ other.points == @points
78
+ end
79
+
80
+ def to_s
81
+ name_str + @points.collect { |p| p.to_s }.join(' ')
82
+ end
83
+
84
+ def self.name_str(sym, absolute)
85
+ str = NAMES.key(sym).dup
86
+ str.upcase! if absolute
87
+ str
88
+ end
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,54 @@
1
+ require 'svgcode/utility'
2
+ require 'svgcode/svg/base_command'
3
+ require 'svgcode/svg/point'
4
+ require 'nokogiri'
5
+
6
+ module Svgcode
7
+ module SVG
8
+ class Circle < BaseCommand
9
+ attr_reader :centre_x, :centre_y, :radius
10
+
11
+ def initialize(element_or_x, y = nil, r = nil)
12
+ @name = :circle
13
+ @absolute = true
14
+
15
+ if element_or_x.is_a?(Nokogiri::XML::Element)
16
+ @centre_x = Utility.x_to_f(element_or_x.attributes['cx'].value)
17
+ @centre_y = Utility.x_to_f(element_or_x.attributes['cy'].value)
18
+ @radius = Utility.x_to_f(element_or_x.attributes['r'].value)
19
+ else
20
+ @centre_x = Utility.x_to_f(element_or_x)
21
+ @centre_y = Utility.x_to_f(y)
22
+ @radius = Utility.x_to_f(r)
23
+ end
24
+
25
+ @points = [ Point.new(@centre_x, @centre_y) ]
26
+ end
27
+
28
+ def start_x
29
+ @centre_x - @radius
30
+ end
31
+
32
+ def apply_transforms!(transforms)
33
+ super(transforms)
34
+
35
+ transforms.reverse.each do |transform|
36
+ r_start = transform.apply(Point.new(start_x, 0))
37
+ r_end = transform.apply(Point.new(@centre_x, 0))
38
+ @centre_x = r_end.x
39
+ @radius = @centre_x - r_start.x
40
+ end
41
+
42
+ @centre_x = @points.first.x
43
+ @centre_y = @points.first.y
44
+ end
45
+
46
+ def divide_points_by!(amount)
47
+ super(amount)
48
+ @centre_x = @points.first.x
49
+ @centre_y = @points.first.y
50
+ @radius /= amount
51
+ end
52
+ end
53
+ end
54
+ end
@@ -1,4 +1,4 @@
1
- require 'svgcode/svg/command'
1
+ require 'svgcode/svg/path_command'
2
2
 
3
3
  module Svgcode
4
4
  module SVG
@@ -6,7 +6,7 @@ module Svgcode
6
6
  attr_reader :commands
7
7
 
8
8
  def initialize(str)
9
- @commands = str.split(/(?=[a-z])/i).collect { |s| Command.new(s) }
9
+ @commands = str.split(/(?=[a-z])/i).collect { |s| PathCommand.new(s) }
10
10
  end
11
11
  end
12
12
  end
@@ -1,8 +1,9 @@
1
1
  require 'svgcode/svg/point'
2
+ require 'svgcode/svg/base_command'
2
3
 
3
4
  module Svgcode
4
5
  module SVG
5
- class Command
6
+ class PathCommand < BaseCommand
6
7
  attr_reader :name, :absolute, :points
7
8
 
8
9
  NAMES = {
@@ -46,7 +47,7 @@ module Svgcode
46
47
 
47
48
  def absolute(pos)
48
49
  points = @points.collect { |p| p + pos }
49
- Command.new(name: @name, absolute: true, points: points)
50
+ PathCommand.new(name: @name, absolute: true, points: points)
50
51
  end
51
52
 
52
53
  def absolute!(pos)
@@ -58,7 +59,7 @@ module Svgcode
58
59
 
59
60
  def negate_points_y
60
61
  points = @points.collect { |point| point.negate_y }
61
- Command.new(name: @name, absolute: @absolute, points: points)
62
+ PathCommand.new(name: @name, absolute: @absolute, points: points)
62
63
  end
63
64
 
64
65
  def negate_points_y!
@@ -74,7 +75,7 @@ module Svgcode
74
75
  def flip_points_y!(max_y)
75
76
  @points.each { |point| point.flip_y!(max_y) }
76
77
  nil
77
- end
78
+ end
78
79
 
79
80
  def apply_transforms!(transforms)
80
81
  unless transforms.empty?
@@ -85,13 +86,13 @@ module Svgcode
85
86
  end
86
87
 
87
88
  def name_str
88
- Command.name_str(@name, absolute?)
89
+ PathCommand.name_str(@name, absolute?)
89
90
  end
90
91
 
91
92
  def ==(other)
92
- other.is_a?(self.class) &&
93
- other.name == @name &&
94
- other.absolute? == @absolute &&
93
+ other.is_a?(self.class) &&
94
+ other.name == @name &&
95
+ other.absolute? == @absolute &&
95
96
  other.points == @points
96
97
  end
97
98
 
@@ -1,3 +1,5 @@
1
+ require 'svgcode/utility'
2
+
1
3
  module Svgcode
2
4
  module SVG
3
5
  class Point
@@ -9,11 +11,11 @@ module Svgcode
9
11
  def initialize(str_or_x, y = nil)
10
12
  if y.nil?
11
13
  parts = str_or_x.split(VALUE_SEP)
12
- @x = Point.str_to_f(parts.first)
13
- @y = Point.str_to_f(parts.last)
14
+ @x = Utility.x_to_f(parts.first)
15
+ @y = Utility.x_to_f(parts.last)
14
16
  else
15
- @x = str_or_x.to_f
16
- @y = y.to_f
17
+ @x = Utility.x_to_f(str_or_x)
18
+ @y = Utility.x_to_f(y)
17
19
  end
18
20
  end
19
21
 
@@ -62,6 +64,12 @@ module Svgcode
62
64
  @y /= amount
63
65
  end
64
66
 
67
+ def flip_y(max_y)
68
+ p = Point.new(@x, @y)
69
+ p.flip_y!(max_y)
70
+ p
71
+ end
72
+
65
73
  def flip_y!(max_y)
66
74
  @y = max_y - @y
67
75
  end
@@ -77,10 +85,6 @@ module Svgcode
77
85
  def self.parse(str)
78
86
  str.split(OBJECT_SEP).collect { |p| Point.new(p.strip) }
79
87
  end
80
-
81
- def self.str_to_f(str)
82
- str.include?('e') ? "%f" % str : str.to_f
83
- end
84
88
  end
85
89
  end
86
90
  end
@@ -1,3 +1,4 @@
1
+ require 'svgcode/utility'
1
2
  require 'svgcode/svg/point'
2
3
  require 'matrix'
3
4
 
@@ -14,26 +15,26 @@ module Svgcode
14
15
  nums.each_with_index do |n, i|
15
16
  case i
16
17
  when 0
17
- @a = n.to_f
18
+ @a = Svgcode::Utility.x_to_f(n)
18
19
  when 1
19
- @b = n.to_f
20
+ @b = Svgcode::Utility.x_to_f(n)
20
21
  when 2
21
- @c = n.to_f
22
+ @c = Svgcode::Utility.x_to_f(n)
22
23
  when 3
23
- @d = n.to_f
24
+ @d = Svgcode::Utility.x_to_f(n)
24
25
  when 4
25
- @e = n.to_f
26
+ @e = Svgcode::Utility.x_to_f(n)
26
27
  when 5
27
- @f = n.to_f
28
+ @f = Svgcode::Utility.x_to_f(n)
28
29
  end
29
30
  end
30
31
  else
31
- @a = str_or_a.to_f
32
- @b = b.to_f
33
- @c = c.to_f
34
- @d = d.to_f
35
- @e = e.to_f
36
- @f = f.to_f
32
+ @a = Svgcode::Utility.x_to_f(str_or_a)
33
+ @b = Svgcode::Utility.x_to_f(b)
34
+ @c = Svgcode::Utility.x_to_f(c)
35
+ @d = Svgcode::Utility.x_to_f(d)
36
+ @e = Svgcode::Utility.x_to_f(e)
37
+ @f = Svgcode::Utility.x_to_f(f)
37
38
  end
38
39
  end
39
40
 
@@ -0,0 +1,28 @@
1
+ module Svgcode
2
+ module Utility
3
+ SCI_SEP = /e/i
4
+
5
+ def self.x_to_f(x)
6
+ f =
7
+ if x.is_a?(Numeric)
8
+ x.to_f
9
+ elsif x.is_a?(String)
10
+ if x.match(SCI_SEP)
11
+ parts = x.split(SCI_SEP)
12
+
13
+ unless parts.length == 2
14
+ raise ArgumentError.new('x is an unknown number format')
15
+ end
16
+
17
+ parts.first.to_f * 10.0 ** parts.last.to_f
18
+ else
19
+ x.to_f
20
+ end
21
+ else
22
+ raise ArgumentError.new('x must be a Numeric or a String')
23
+ end
24
+
25
+ f
26
+ end
27
+ end
28
+ end
@@ -1,3 +1,3 @@
1
1
  module Svgcode
2
- VERSION = '0.4.0'
2
+ VERSION = '0.6.0'
3
3
  end
@@ -23,8 +23,11 @@ Gem::Specification.new do |spec|
23
23
  spec.add_development_dependency 'bundler', '~> 1.16'
24
24
  spec.add_development_dependency 'rake', '~> 10.0'
25
25
  spec.add_development_dependency 'rspec', '~> 3.0'
26
+
26
27
  spec.add_development_dependency 'byebug'
27
28
  spec.add_development_dependency 'yard'
29
+ spec.add_development_dependency 'guard'
30
+ spec.add_development_dependency 'guard-shell'
28
31
 
29
32
  spec.add_dependency 'nokogiri', '~> 1.8'
30
33
  spec.add_dependency 'thor', '~> 0.20'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: svgcode
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ben Williams
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-02-18 00:00:00.000000000 Z
11
+ date: 2018-04-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -80,6 +80,34 @@ dependencies:
80
80
  - - ">="
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: guard
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: guard-shell
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
83
111
  - !ruby/object:Gem::Dependency
84
112
  name: nokogiri
85
113
  requirement: !ruby/object:Gem::Requirement
@@ -119,6 +147,7 @@ files:
119
147
  - ".gitignore"
120
148
  - Gemfile
121
149
  - Gemfile.lock
150
+ - Guardfile
122
151
  - LICENSE.txt
123
152
  - README.md
124
153
  - README/linux-cnc-reverb.png
@@ -129,14 +158,18 @@ files:
129
158
  - bin/setup
130
159
  - bin/svgcode
131
160
  - lib/svgcode.rb
161
+ - lib/svgcode/cli.rb
132
162
  - lib/svgcode/gcode/command.rb
133
163
  - lib/svgcode/gcode/converter.rb
134
164
  - lib/svgcode/gcode/invalid_command_error.rb
135
165
  - lib/svgcode/gcode/program.rb
136
- - lib/svgcode/svg/command.rb
166
+ - lib/svgcode/svg/base_command.rb
167
+ - lib/svgcode/svg/circle.rb
137
168
  - lib/svgcode/svg/path.rb
169
+ - lib/svgcode/svg/path_command.rb
138
170
  - lib/svgcode/svg/point.rb
139
171
  - lib/svgcode/svg/transform.rb
172
+ - lib/svgcode/utility.rb
140
173
  - lib/svgcode/version.rb
141
174
  - svgcode.gemspec
142
175
  homepage: https://github.com/benjineering/svgcode