laser-cutter 0.3.2 → 0.4.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: 281b7861f4452cfb6323f9d2a4a05aff6db5a742
4
- data.tar.gz: dd4e65121d84f8a285dd3c603d1674a5505af9f4
3
+ metadata.gz: df5fc0b8025663e5d008e970a56fa3fe49f5a275
4
+ data.tar.gz: c9a4201c05edf34506255706906d979249047b92
5
5
  SHA512:
6
- metadata.gz: d42068728244eb2d1125a9f3e759d5c00e1623a15f29e0eede7deb4eb3a5711f717434f81d2c99fd400d346e3e9b6832e47cb932830171b55cc9fa551f0d979a
7
- data.tar.gz: 65ab7c551ef9f144dc8f91e9898d526e60ac42246c779cb9d480aea6d2f3e36e44514ccc3ff7ff802bdf30097d34d3127adc4a928ec9fa9bb78317302d0bb104
6
+ metadata.gz: 88b3fbacb5fbc6f0049f7799a7721f9b22ccff4ddfe313496a051b931ce5b9184efd273b68981234038f3d5967e1b073d0d8bbe6aa88a35a925bd4f2ab7b343f
7
+ data.tar.gz: 4c816f055a6f32109305ece7f3b7e2cb98d69d71b70d2e8cc6f7c566edd475c3cb6cb8a53de4a1598187f0b88ba170026acecd1a09329b0d8f0f4567e2581c08
data/.gitignore CHANGED
@@ -24,3 +24,4 @@ tmp
24
24
  mkmf.log
25
25
  .idea/
26
26
  **output.pdf
27
+ .ruby_version
data/.travis.yml CHANGED
@@ -1,7 +1,7 @@
1
1
  language: ruby
2
2
  rvm:
3
3
  - 1.9.3
4
- script: "bundle exec rspec"
4
+ script: "CODECLIMATE_REPO_TOKEN=6520104decf84e2f6c2c169d30d67976bfcdaa48cd89b4ec34f6e637f2a0ae02 bundle exec rspec"
5
5
  notifications:
6
6
  email:
7
7
  recipients:
data/Gemfile CHANGED
@@ -2,3 +2,5 @@ source 'https://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in laser-cutter-cutter.gemspec
4
4
  gemspec
5
+
6
+ gem "codeclimate-test-reporter", group: :test, require: nil
data/README.md CHANGED
@@ -1,68 +1,28 @@
1
1
  [![Gem Version](https://badge.fury.io/rb/laser-cutter.svg)](http://badge.fury.io/rb/laser-cutter)
2
2
  [![Build status](https://secure.travis-ci.org/kigster/laser-cutter.png)](http://travis-ci.org/kigster/laser-cutter)
3
3
  [![Code Climate](https://codeclimate.com/github/kigster/laser-cutter.png)](https://codeclimate.com/github/kigster/laser-cutter)
4
+ [![Test Coverage](https://codeclimate.com/github/kigster/laser-cutter/badges/coverage.svg)](https://codeclimate.com/github/kigster/laser-cutter)
4
5
 
5
6
  ## LaserCutter
6
7
 
7
8
  Similar to [BoxMaker](https://github.com/rahulbot/boxmaker/) (which is written in Java a long time ago),
8
- this ruby gem generates PDFs that can be used as a basis for cutting boxes on a typical laser cutter.
9
+ this ruby gem generates PDFs that can be used as a basis for creating a "snap-in" boxes with notched
10
+ sides on a typical laser cutter, by providing dimensions, material thickness and output file name.
9
11
 
10
- Unlike ```BoxMaker```, this gem has a lot of automated tests around creating the geometry of the notches
11
- and calculating locations. This welcomes additional feature contributions from other developers,
12
- as existing test suite offers confidence around not introducing bugs or regressions.
12
+ For more detailed comparison with BoxMaker and motivation behind this project, please see the section
13
+ at the bottom of this README.
13
14
 
14
- BoxMaker's algorithm _ensures that the same notch length is across all sides, but sacrifices
15
- symmetry as a result_. So you may have a front panel's left and right edges be simply non symmetric.
16
- And that might be entirely OK with you :)
17
-
18
- ```laser-cutter```'s algorithm will create a _symmetric design for most panels_, but it might sacrifice
19
- identical notch length. Depending on the box dimensions you may end up with a slightly different notch
20
- length on each side of the box.
21
-
22
- Having said that, one of the design goals of this ruby version is to provide a highly extensible platform,
23
- where alternative algorithms can be implemented and supported by command line options.
24
-
25
- ```laser-cutter``` has quite a few options that allow you to set stroke width, page size,
26
- layout, margins, padding (spacing between boxes), open the PDF file using system viewer right
27
- after generation, and many more are coming soon.
28
-
29
- The choice ultimately comes down to the preference and feature set, so here I show you two boxes made with
30
- each program, so you can pick what you prefer.
31
-
32
- #### Disclaimer
33
-
34
- Important quick note that the author believes that BoxMaker is a greatly useful piece of software
35
- generously open sourced by the author, and so in no way this project disputes it's viability.
36
- In fact BoxMaker was an inspiration for this project. This project simply attempts to advance
37
- further and provide additional solutions to this complex problem of creating 3D designs on a 2D
38
- surface using laser cutter.
39
-
40
- ### Example Outputs
41
-
42
- Below are two examples of boxes with identical dimensions produced with ```laser-cutter``` and ```boxmaker```:
43
-
44
- #### BoxMaker
45
-
46
- ```bash
47
- > java -cp BOX.jar com.rahulbotics.boxmaker.BoxMaker -i -W 2.5 -H 2 -D 1 -T 0.25 -n 0.5 -f file.pdf
48
- ```
49
-
50
- ![BoxMaker Example](doc/boxmaker.jpg).
15
+ One of the design goals of this project is to provide a highly extensible platform for creating
16
+ laser-cut designs, where alternative strategies can be added over time, and supported by various
17
+ command line options, and perhaps a light weight web application. If you are interested in
18
+ contributing to the project, please see [contributing](CONTRIBUTING.md) for more details.
51
19
 
52
- #### LaserCutter
20
+ ```laser-cutter``` supports many flexible command line options that allow setting dimensions,
21
+ stroke width, page size, layout, margins, padding (spacing between the boxes), and many more.
53
22
 
54
- ```bash
55
- > laser-cutter -u in -s 2.5x1x2/0.25/0.5 -o file.pdf
56
- ```
57
-
58
- ![LaserCutter Example](doc/laser-cutter.jpg).
23
+ ## Dependencies
59
24
 
60
- ## Future Features
61
-
62
- * Creating T-style joins, using various sized nuts and bolts (such as common #4-40 and M2 sizes)
63
- * Creating lids and front panels that are larger than the box
64
- * Rendering to CSS to show live preview on a web app
65
- * Your brilliant idea can be here! Please see [contributing](CONTRIBUTING.md) for more info.
25
+ The gem depends primarily on [Prawn](http://prawnpdf.org) – a fantastic PDF generation library.
66
26
 
67
27
  ## Installation
68
28
 
@@ -81,44 +41,110 @@ Or install it yourself as:
81
41
  ## Usage
82
42
 
83
43
  ```bash
84
- Usage: laser-cutter [options]
85
- laser-cutter --list-all-page-sizes --units in
86
-
87
- Examples:
88
- 1. Create a box defined in inches, and open PDF in preview right after:
89
-
90
- laser-cutter --units in -s 3x2x2/0.125/0.5 -O -o box.pdf
91
-
92
- 2. Create a box defined in millimeters, print verbose info and set
93
- page size to A3, and layout to landscape, and stroke width to 2mm:
94
-
95
- laser-cutter -w70 -h20 -d50 -t4.3 -n5 -PA3 -L landscape -S 0.5 -v -O -o box.pdf
96
-
97
-
98
- Specific options:
99
- -s, --size WxHxD/T/N Combined internal dimensions: W = width, H = height,
100
- D = depth, T = thickness, N = notch length
44
+ Usage: laser-cutter [options] -o filename.pdf
45
+ eg: laser-cutter -i -s 1x1.5x2/0.125/0.125 -O -o box.pdf
101
46
 
47
+ Specific Options:
102
48
  -w, --width WIDTH Internal width of the box
103
49
  -h, --height HEIGHT Internal height of the box
104
50
  -d, --depth DEPTH Internal depth of the box
105
51
  -t, --thickness THICKNESS Thickness of the box material
106
52
  -n, --notch NOTCH Preferred notch length (used only as a guide)
107
- -o, --file FILE Output filename of the PDF
108
- -u, --units UNITS Either 'mm' (default) or 'in'
53
+
109
54
  -m, --margin MARGIN Margins from the edge of the document
110
55
  -p, --padding PADDING Space between the boxes on the page
56
+ -S, --stroke WIDTH Numeric stroke width of the line
111
57
  -P, --page_size LETTER Page size, see --list-all-page-sizes for more info.
112
58
  -L, --page_layout portrait Page layout, other option is 'landscape'
113
- -S, --stroke WIDTH Numeric stroke width of the line
59
+
114
60
  -O, --open Open generated file with system viewer before exiting
61
+ -u, --units UNITS Either 'mm' (default) or 'in'
62
+
115
63
  -A, --list-all-page-sizes Print all available page sizes with dimensions and exit
116
64
  -v, --[no-]verbose Run verbosely
117
65
 
118
- Common options:
66
+ --examples Show detailed usage examples
119
67
  --help Show this message
120
68
  --version Show version
121
- ```
69
+
70
+ Common Options:
71
+ -o, --file FILE Required output filename of the PDF
72
+ -s, --size WxHxD/T/N Combined internal dimensions: W = width, H = height,
73
+ D = depth, T = thickness, N = notch length
74
+
75
+ -i, --inches Switch measurements to inches instead of millimeters
76
+
77
+ Examples:
78
+ 1. Create a box defined in inches, and open PDF in preview right after:
79
+
80
+ laser-cutter -i -s 3x2x2/0.125/0.5 -O -o box.pdf
81
+
82
+ 2. Create a box defined in millimeters, print verbose info and set
83
+ page size to A3, and layout to landscape, and stroke width to 1/2mm:
84
+
85
+ laser-cutter -w70 -h20 -d50 -t4.3 -n5 -PA3 -L landscape -S0.5 -v -O -o box.pdf
86
+
87
+ 3. List all possible page sizes in metric or imperial systems:
88
+
89
+ laser-cutter --list-all-page-sizes
90
+ laser-cutter --list-all-page-sizes --inches
91
+ ```
92
+
93
+ ## Future Features
94
+
95
+ * Extensibility with various layout strategies, notch drawing strategies, basically plug and play
96
+ model for adding new algorithms for path creation and box joining
97
+ * Support more shapes than just box
98
+ * Create T-style joins, using various standard sizes of nuts and bolts (such as common #4-40 and M2 sizes)
99
+ * Supporting lids and front panels, that are larger than the box itself and have holes for notches.
100
+ * A web-app that uses the gem and renders box live in CSS using CSS 2D to show preview.
101
+ * Your brilliant idea can be here too! Please see [contributing](CONTRIBUTING.md) for more info.
102
+
103
+ ## Comparison with BoxMaker
104
+
105
+ It's important to note that the author believes that BoxMaker is a greatly useful piece of software
106
+ generously open sourced by the author, and so in no way this project disputes BoxMaker's viability.
107
+
108
+ In fact BoxMaker was an inspiration for this project. Laser-Cutter library attempts to further advance
109
+ concept of programmatically creating laser-cut boxes, provide additional tuning, options, strategies
110
+ and most importantly – extensibility.
111
+
112
+ Unlike ```BoxMaker```, this gem has a suit of automated tests (rspecs) around creating the geometry.
113
+ In addition, we welcome new feature contributions, or bug fixes from other developers, and in that
114
+ regard rspecs offer confidence that functionality still works.
115
+
116
+ BoxMaker's algorithm _tries to ensures that the same notch length is across all sides, but sacrifices
117
+ symmetry as a result_. So you may have a front panel's left and right edges be simply non symmetric.
118
+ And that might be entirely OK with you :)
119
+
120
+ ```laser-cutter```'s algorithm will create a _symmetric design for most panels_, but it might sacrifice
121
+ identical notch length. Depending on the box dimensions you may end up with a slightly different notch
122
+ length on each side of the box.
123
+
124
+ The choice ultimately comes down to the preference and feature set, so here I show you two boxes made with
125
+ each program, so you can pick what you prefer.
126
+
127
+ ### Example Outputs
128
+
129
+ Below are two examples of boxes with identical dimensions produced with ```laser-cutter``` and ```boxmaker```:
130
+
131
+ This is how you would make a box with Adam Phelp's fork of BoxMaker (which adds flags and a lot of
132
+ niceties):
133
+
134
+ ```bash
135
+ git clone https://github.com/aphelps/boxmaker && cd boxmaker && ant
136
+ java -cp BOX.jar com.rahulbotics.boxmaker.BoxMaker \
137
+ -i -W 1 -H 2 -D 1.5 -T 0.125 -n 0.125 -f box.pdf
138
+ ```
139
+
140
+ And laser-cutter:
141
+
142
+ ```bash
143
+ gem install laser-cutter
144
+ laser-cutter -i -s 1x1.5x2/0.125/0.125 -O -o box.pdf
145
+ ```
146
+
147
+ ![LaserCutter Comparison](doc/comparison.jpg).
122
148
 
123
149
  ## Contributing
124
150
 
data/bin/laser-cutter CHANGED
@@ -8,122 +8,107 @@ require 'hashie/mash'
8
8
  module Laser
9
9
  module Cutter
10
10
  class OptParse
11
+ def self.puts_error(e)
12
+ STDERR.puts "Whoops, #{e}".red
13
+ STDERR.puts "Try --help or --examples for more info...".yellow
14
+ end
15
+
11
16
  def self.parse(args)
12
17
  banner_text = <<-EOF
13
- Usage: laser-cutter [options]
14
- laser-cutter --list-all-page-sizes --units in
18
+ #{('Laser-Cutter v'+ Laser::Cutter::VERSION).bold}
19
+
20
+ Usage: laser-cutter [options] -o filename.pdf
21
+ eg: laser-cutter -i -s 1x1.5x2/0.125/0.125 -O -o box.pdf
22
+ EOF
23
+
24
+ examples = <<-EOF
15
25
 
16
26
  Examples:
17
27
  1. Create a box defined in inches, and open PDF in preview right after:
18
28
 
19
- laser-cutter --units in -s 3x2x2/0.125/0.5 -O -o box.pdf
29
+ laser-cutter -i -s 3x2x2/0.125/0.5 -O -o box.pdf
20
30
 
21
31
  2. Create a box defined in millimeters, print verbose info and set
22
- page size to A3, and layout to landscape, and stroke width to 2mm:
32
+ page size to A3, and layout to landscape, and stroke width to 1/2mm:
23
33
 
24
- laser-cutter -w70 -h20 -d50 -t4.3 -n5 -PA3 -L landscape -S 0.5 -v -O -o box.pdf
25
- EOF
34
+ laser-cutter -w70 -h20 -d50 -t4.3 -n5 -PA3 -L landscape -S0.5 -v -O -o box.pdf
35
+
36
+ 3. List all possible page sizes in metric or imperial systems:
26
37
 
38
+ laser-cutter --list-all-page-sizes
39
+ laser-cutter --list-all-page-sizes --inches
40
+ EOF
27
41
  options = Hashie::Mash.new
28
42
  options.verbose = false
29
43
  options.units = 'mm'
30
44
 
31
45
  opt_parser = OptionParser.new do |opts|
32
- opts.banner = banner_text.cyan
33
- opts.separator ""
34
- opts.separator "Specific options:"
35
-
36
- opts.on("-s", "--size WxHxD/T/N",
37
- "Combined internal dimensions: W = width, H = height,\n#{" " * 37}D = depth, T = thickness, N = notch length\n\n") do |size|
38
- options.size = size
39
- end
40
-
46
+ opts.banner = banner_text.blue
47
+ opts.separator "Specific Options:"
41
48
  opts.on("-w", "--width WIDTH", "Internal width of the box") { |value| options.width = value }
42
49
  opts.on("-h", "--height HEIGHT", "Internal height of the box") { |value| options.height = value }
43
50
  opts.on("-d", "--depth DEPTH", "Internal depth of the box") { |value| options.depth= value }
44
-
45
51
  opts.on("-t", "--thickness THICKNESS", "Thickness of the box material") { |value| options.thickness = value }
46
52
  opts.on("-n", "--notch NOTCH", "Preferred notch length (used only as a guide)") { |value| options.notch = value }
47
- opts.on("-o", "--file FILE", "Output filename of the PDF") { |value| options.file = value }
48
-
49
- opts.on("-u", "--units UNITS", "Either 'mm' (default) or 'in'") { |value| options.units = value }
53
+ opts.separator ""
50
54
  opts.on("-m", "--margin MARGIN", "Margins from the edge of the document") { |value| options.margin = value }
51
55
  opts.on("-p", "--padding PADDING", "Space between the boxes on the page") { |value| options.padding = value }
52
-
56
+ opts.on("-S", "--stroke WIDTH", "Numeric stroke width of the line") { |value| options.stroke = value }
53
57
  opts.on("-P", "--page_size LETTER", "Page size, see --list-all-page-sizes for more info.") { |value| options.page_size = value }
54
58
  opts.on("-L", "--page_layout portrait", "Page layout, other option is 'landscape' ") { |value| options.page_layout = value }
55
- opts.on("-S", "--stroke WIDTH", "Numeric stroke width of the line") { |value| options.stroke = value }
56
-
59
+ opts.separator ""
57
60
  opts.on("-O", "--open", "Open generated file with system viewer before exiting") { |v| options.open = v }
58
-
61
+ opts.on("-u", "--units UNITS", "Either 'mm' (default) or 'in'") { |value| options.units = value }
62
+ opts.separator ""
59
63
  opts.on("-A", "--list-all-page-sizes", "Print all available page sizes with dimensions and exit") { |v| options.list_all_page_sizes = true }
60
-
61
64
  opts.on("-v", "--[no-]verbose", "Run verbosely") { |v| options.verbose = v }
62
-
63
65
  opts.separator ""
64
- opts.separator "Common options:"
65
-
66
- opts.on_tail("--help", "Show this message") do
67
- puts opts
68
- exit
69
- end
70
- opts.on_tail("--version", "Show version") do
71
- puts Laser::Cutter::VERSION
72
- exit
66
+ opts.on("--examples", "Show detailed usage examples") { puts opts; puts examples.yellow; exit }
67
+ opts.on("--help", "Show this message") { puts opts; exit }
68
+ opts.on("--version", "Show version") { puts Laser::Cutter::VERSION; exit }
69
+ opts.separator ""
70
+ opts.separator "Common Options:"
71
+ opts.on_tail("-o", "--file FILE", "Required output filename of the PDF") { |value| options.file = value }
72
+ opts.on_tail("-s", "--size WxHxD/T/N",
73
+ "Combined internal dimensions: W = width, H = height,\n#{" " * 37}D = depth, T = thickness, N = notch length\n\n") do |size|
74
+ options.size = size
73
75
  end
76
+ opts.on_tail("-i", "--inches", "Switch measurements to inches instead of millimeters") { |value| options.units = 'in' }
74
77
  end
78
+
75
79
  opt_parser.parse!(args)
76
- options
77
- rescue OptionParser::InvalidOption, OptionParser::MissingArgument => e
78
- puts opt_parser.help
79
- puts
80
- puts "#{e.message}".red
80
+
81
+ config = Laser::Cutter::Configuration.new(options.to_hash)
82
+ if config.list_all_page_sizes
83
+ puts config.all_page_sizes
84
+ exit 0
85
+ end
86
+
87
+ if options.verbose
88
+ puts "Starting with the following configuration:"
89
+ puts JSON.pretty_generate(config.to_hash).green
90
+ end
91
+
92
+ config.validate!
93
+ config
94
+ rescue OptionParser::InvalidOption, OptionParser::MissingArgument, Laser::Cutter::MissingOption => e
95
+ puts opt_parser.banner.blue
96
+ puts_error(e)
81
97
  exit 1
82
98
  end # end parse()
83
99
  end
84
100
  end
85
101
  end # class OptParse
86
102
 
87
- options = Laser::Cutter::OptParse.parse(ARGV)
88
-
89
- if options.list_all_page_sizes
90
- puts
91
- unit = 1.0 / 72.0 # PDF units per inch
92
- multiplier = options.units == 'in' ? 1.0 : 25.4
93
- hash = PDF::Core::PageGeometry::SIZES
94
- hash.keys.sort.each do |k|
95
- printf("\t%10s:\t%6.1f x %6.1f\n",
96
- k,
97
- multiplier * hash[k][0].to_f * unit,
98
- multiplier * hash[k][1].to_f * unit )
99
- end
100
- exit 0
101
- end
102
-
103
- config = Laser::Cutter::Configuration.new(options.to_hash)
104
-
105
- if options.verbose
106
- puts "Starting with the following configuration:"
107
- puts JSON.pretty_generate(config.to_hash).green
108
- end
109
-
110
- begin
111
- config.validate!
112
- rescue Exception => e
113
- STDERR.puts "\nSorry, #{e}".red
114
- STDERR.puts "Try --help for more info..."
115
- exit 1
116
- end
103
+ config = Laser::Cutter::OptParse.parse(ARGV)
117
104
 
118
105
  begin
119
- box = Laser::Cutter::Box.new(config)
120
- Laser::Cutter::Renderer::BoxRenderer.new(box, config).render
106
+ Laser::Cutter::Renderer::BoxRenderer.new(config).render
121
107
  if config.open
122
108
  `open #{config.file}`
123
109
  end
124
110
  rescue Exception => e
125
- puts "#{e}".red
126
- STDERR.puts "Try --help for more info...".yellow
111
+ puts_error(e)
127
112
  if options.verbose
128
113
  STDERR.puts "Exception: #{e.inspect}".red
129
114
  STDERR.puts e.backtrace.join("\n").red
Binary file
@@ -1,5 +1,7 @@
1
1
  module Laser
2
2
  module Cutter
3
+ # Note: this class badly needs refactoring and tests. Both are coming.
4
+
3
5
  class Box
4
6
  # Everything is in millimeters
5
7
 
@@ -7,7 +9,7 @@ module Laser
7
9
  attr_accessor :padding, :units
8
10
 
9
11
  attr_accessor :front, :back, :top, :bottom, :left, :right
10
- attr_accessor :faces, :bounds, :conf
12
+ attr_accessor :faces, :bounds, :conf, :corner_face
11
13
 
12
14
  def initialize(config = {})
13
15
  self.dim = Geometry::Dimensions.new(config['width'], config['height'], config['depth'])
@@ -18,32 +20,35 @@ module Laser
18
20
  self.units = config['units']
19
21
 
20
22
  create_faces! # generates dimensions for each side
21
- self.faces = [top, front, bottom, back, left, right]
23
+ self.faces = [top, front, bottom, back, left, right]
22
24
 
23
25
  position_faces!
26
+
24
27
  self.conf = {
25
- valign: [ :out, :out, :out, :out, :in, :in],
26
- halign: [ :in, :out, :in, :out, :in, :in],
27
- corners:[ :no, :yes, :no, :yes, :no, :no]
28
+ valign: [ :out, :out, :out, :out, :in, :in],
29
+ halign: [ :in, :out, :in, :out, :in, :in],
30
+ corners: {
31
+ front: [ :no, :yes, :no, :yes, :no, :no], # our default choice, but may not work
32
+ top: [ :yes, :no, :yes, :no, :no, :no] # 2nd choice, has to work if 1st doesn't
33
+ },
28
34
  }
29
-
30
35
  self
31
36
  end
32
37
 
38
+
33
39
  # Returns an flattened array of lines representing notched
34
40
  # rectangle.
35
41
  def notches
36
- generate_bounding_boxes!
42
+ corner_face = pick_corners_face
37
43
 
38
44
  notches = []
39
-
40
45
  faces.each_with_index do |face, face_index|
41
- bound = bounds[face_index]
46
+ bound = face_bounding_rect(face)
42
47
  bound.sides.each_with_index do |bounding_side, side_index |
43
48
  key = side_index.odd? ? :valign : :halign
44
49
  path = Geometry::PathGenerator.new(:notch_width => notch_width,
45
50
  :center_out => (self.conf[key][face_index] == :out) ,
46
- :fill_corners => (self.conf[:corners][face_index] == :yes && side_index.odd?),
51
+ :fill_corners => (self.conf[:corners][corner_face][face_index] == :yes && side_index.odd?),
47
52
  :thickness => thickness
48
53
  ).path(Geometry::Edge.new(bounding_side, face.sides[side_index], self.notch_width))
49
54
  notches << path.create_lines
@@ -67,15 +72,11 @@ module Laser
67
72
 
68
73
  private
69
74
 
70
- def generate_bounding_boxes!
71
- self.bounds = []
72
- self.bounds = faces.map do |face|
73
- b = face.clone
74
- b.move_to(b.position.move_by(-thickness, -thickness))
75
- b.p2 = b.p2.move_by(2 * thickness, 2 * thickness)
76
- b.relocate!
77
- b
78
- end
75
+ def face_bounding_rect(face)
76
+ b = face.clone
77
+ b.move_to(b.position.move_by(-thickness, -thickness))
78
+ b.p2 = b.p2.move_by(2 * thickness, 2 * thickness)
79
+ b.relocate!
79
80
  end
80
81
 
81
82
  #___________________________________________________________________
@@ -131,6 +132,15 @@ module Laser
131
132
  self.right = Geometry::Rect.create(zero, dim.d, dim.h, "right")
132
133
  end
133
134
 
135
+ def pick_corners_face
136
+ b = face_bounding_rect(front)
137
+ edges = []
138
+ front.sides[0..1].each_with_index do |face, index|
139
+ edges << Geometry::Edge.new(b.sides[index], face, notch_width)
140
+ end
141
+ edges.map(&:notch_count).all?{|c| c % 4 == 3} ? :top : :front
142
+ end
143
+
134
144
  end
135
145
  end
136
146
  end
@@ -1,9 +1,11 @@
1
1
  require 'hashie/mash'
2
2
  require 'prawn/measurement_extensions'
3
-
3
+ require 'pdf/core/page_geometry'
4
4
 
5
5
  module Laser
6
6
  module Cutter
7
+ class MissingOption < RuntimeError
8
+ end
7
9
  class Configuration < Hashie::Mash
8
10
  DEFAULTS = {
9
11
  units: 'mm',
@@ -49,7 +51,23 @@ module Laser
49
51
  REQUIRED.each do |k|
50
52
  missing << k if self[k].nil?
51
53
  end
52
- raise "#{missing.join(', ')} #{missing.size > 1 ? 'are' : 'is'} required, but missing." unless missing.empty?
54
+ unless missing.empty?
55
+ raise MissingOption.new("#{missing.join(', ')} #{missing.size > 1 ? 'are' : 'is'} required, but missing.")
56
+ end
57
+ end
58
+
59
+ def all_page_sizes
60
+ unit = 1.0 / 72.0 # PDF units per inch
61
+ multiplier = (self.units == 'in') ? 1.0 : 25.4
62
+ h = PDF::Core::PageGeometry::SIZES
63
+ output = "\n"
64
+ h.keys.sort.each do |k|
65
+ output << sprintf("\t%10s:\t%6.1f x %6.1f\n",
66
+ k,
67
+ multiplier * h[k][0].to_f * unit,
68
+ multiplier * h[k][1].to_f * unit )
69
+ end
70
+ output
53
71
  end
54
72
  end
55
73
  end
@@ -5,12 +5,15 @@ module Laser
5
5
  module Renderer
6
6
  class BoxRenderer < AbstractRenderer
7
7
  alias_method :box, :subject
8
+ def initialize(options = {})
9
+ self.options = options
10
+ self.subject = Laser::Cutter::Box.new(options)
11
+ end
8
12
 
9
13
  def render pdf = nil
10
14
  pdf = Prawn::Document.new(:margin => options.margin.send(options.units),
11
15
  :page_size => options.page_size,
12
16
  :page_layout => options.page_layout.to_sym)
13
-
14
17
  header = <<-EOF
15
18
 
16
19
  Produced with Laser Cutter Ruby Gem (v#{Laser::Cutter::VERSION})
@@ -1,5 +1,5 @@
1
1
  module Laser
2
2
  module Cutter
3
- VERSION = "0.3.2"
3
+ VERSION = "0.4.0"
4
4
  end
5
5
  end
@@ -3,10 +3,10 @@ require_relative 'spec_helper'
3
3
  module Laser
4
4
  module Cutter
5
5
  describe Configuration do
6
- let(:config) { Laser::Cutter::Configuration.new(opts)}
6
+ let(:config) { Laser::Cutter::Configuration.new(opts) }
7
7
 
8
8
  context 'option parsing' do
9
- let(:opts) { { "size" => "2x3x2/0.125/0.5", "inches" => true} }
9
+ let(:opts) { {"size" => "2x3x2/0.125/0.5", "inches" => true} }
10
10
  it 'should be able to parse size options' do
11
11
  expect(config.width).to eql(2.0)
12
12
  expect(config.height).to eql(3.0)
@@ -15,14 +15,30 @@ module Laser
15
15
  expect(config.notch).to eql(0.5)
16
16
  end
17
17
  end
18
- context 'validate' do
19
- let(:opts) {{ "height" => "23" }}
18
+ context '#validate' do
19
+ let(:opts) { {"height" => "23"} }
20
20
  it 'should be able to validate missing options' do
21
21
  expect(config.height).to eql(23.0)
22
- expect { config.validate! } .to raise_error(RuntimeError)
22
+ expect { config.validate! }.to raise_error(Laser::Cutter::MissingOption)
23
23
  end
24
24
  end
25
+ context '#list_page_sizes' do
26
+ context 'formatting of output' do
27
+ context 'when using inches' do
28
+ let(:opts) { {"units" => "in"} }
29
+ it 'should return the list in inches' do
30
+ expect(config.all_page_sizes).to match %r(.*B10\:\s+1\.2\s+x\s+1\.7)
31
+ end
32
+ end
33
+ context 'when using mm' do
34
+ let(:opts) { {"units" => "mm"} }
35
+ it 'should return the list in mm' do
36
+ expect(config.all_page_sizes).to match %r(.*B10\:\s+31\.0\s+x\s+44\.0)
37
+ end
38
+ end
39
+ end
25
40
 
41
+ end
26
42
  end
27
43
  end
28
44
  end
@@ -6,7 +6,7 @@ module Laser
6
6
  describe 'BoxRenderer' do
7
7
  context '#render' do
8
8
  let(:box) { Laser::Cutter::Box.new(config) }
9
- let(:renderer) { BoxRenderer.new(box, config) }
9
+ let(:renderer) { BoxRenderer.new(config) }
10
10
  let(:file) { File.expand_path("../../laser-cutter-pdf-test.#{$$}.pdf", __FILE__) }
11
11
 
12
12
  def render_file filename
data/spec/spec_helper.rb CHANGED
@@ -5,12 +5,18 @@
5
5
  #
6
6
  # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
7
7
 
8
+ if ENV['CODECLIMATE_REPO_TOKEN']
9
+ require 'codeclimate-test-reporter'
10
+ CodeClimate::TestReporter.start
11
+ end
12
+
8
13
  ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __FILE__)
9
14
  require 'rubygems'
10
15
  require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE'])
11
16
  require 'laser-cutter'
17
+ require "codeclimate-test-reporter"
18
+
12
19
 
13
- #Dir['spec/support/**/*.rb'].each { |filename| require_relative "../#{filename}" }
14
20
 
15
21
  RSpec.configure do |config|
16
22
  config.treat_symbols_as_metadata_keys_with_true_values = true
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: laser-cutter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.2
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Konstantin Gredeskoul
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-09-22 00:00:00.000000000 Z
11
+ date: 2014-09-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: prawn
@@ -115,8 +115,7 @@ files:
115
115
  - README.md
116
116
  - Rakefile
117
117
  - bin/laser-cutter
118
- - doc/boxmaker.jpg
119
- - doc/laser-cutter.jpg
118
+ - doc/comparison.jpg
120
119
  - laser-cutter.gemspec
121
120
  - lib/laser-cutter.rb
122
121
  - lib/laser-cutter/box.rb
@@ -180,4 +179,3 @@ test_files:
180
179
  - spec/rect_spec.rb
181
180
  - spec/renderer_spec.rb
182
181
  - spec/spec_helper.rb
183
- has_rdoc:
data/doc/boxmaker.jpg DELETED
Binary file
data/doc/laser-cutter.jpg DELETED
Binary file