laser-cutter 1.0.3 → 1.0.5

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b027c579de8cded3aba462a120045ed6ec685930
4
- data.tar.gz: 76e13dddecbae505385b1064cb29198c7a0a5d41
3
+ metadata.gz: 3a3d7b723ed7171e84a93783545f037adeeeb122
4
+ data.tar.gz: d3571947154cda05176e1d1bbb84d8d2ee140c02
5
5
  SHA512:
6
- metadata.gz: 843bd8781e86f9da4d6bee52529f625d7b04f177c1a3bf50847b33a51bcb938ce6310faf10b1f0bee57de4d21ee36427515ddfc1529e0c933f21ca268e842091
7
- data.tar.gz: 337ae8d3ebe98ce3dc4380ef65a81c9172eb75ae7f799f60db35f228b2bd6713b525c6898c67dbff00da8de8ecd8adac8cff0d14e9d2d22c23e0598744f40294
6
+ metadata.gz: 870c36a4b07b2d4190076c524917f4322d599c58f5ff9b226b47e00a011dd63f722a7153ed885c192cbe0caefbda17fb150269a7822f4e36a001f4913a435d19
7
+ data.tar.gz: 67c264109139865d62292cb8cea2573ec5dbc569fec92316b00a14f942c0ea15d096d0391d1a5a275e3eaf78c7f9f8f179e95331f93859df982f7c7a80589e08
data/.gitignore CHANGED
@@ -25,3 +25,4 @@ mkmf.log
25
25
  .idea/
26
26
  **output.pdf
27
27
  .ruby_version
28
+ doc
data/.rspec CHANGED
@@ -1,3 +1,2 @@
1
1
  --color
2
2
  --format progress
3
- --require rspec/legacy_formatters
@@ -1,11 +1,26 @@
1
+ env:
2
+ global:
3
+ - CC_TEST_REPORTER_ID=6520104decf84e2f6c2c169d30d67976bfcdaa48cd89b4ec34f6e637f2a0ae02
4
+ sudo: false
1
5
  language: ruby
6
+ cache: bundler
2
7
  rvm:
3
- - 2.1.3
4
- script: "CODECLIMATE_REPO_TOKEN=6520104decf84e2f6c2c169d30d67976bfcdaa48cd89b4ec34f6e637f2a0ae02 bundle exec rspec"
8
+ - 2.4.1
9
+ - 2.3.5
10
+ before_install: gem install bundler -v 1.15.4
11
+ before_script:
12
+ - curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64
13
+ > ./cc-test-reporter
14
+ - chmod +x ./cc-test-reporter
15
+ - "./cc-test-reporter before-build"
16
+ script:
17
+ - bundle exec rspec
18
+ after_script:
19
+ - "./cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT"
5
20
  notifications:
6
- email:
7
- recipients:
8
- - kigster@gmail.com
9
- on_success: never
10
- on_failure: always
11
-
21
+ webhooks:
22
+ urls:
23
+ - secure: fgpv34jAm3rDNjiWuQtuijE0p9B2bpsCWdoCQ82pDZwktSITmNjanYCoZC0hlEw/kqMBDKRN78HfIIidy8dS664sLz8KyaFXq7RWAFsMP9fn/GMG/r9B+S3YumifQ/Zy+3OGa+0Qz76075q291QfNSPv0Y5QDMoAU5VljIVashC/qJS6DRO+vekDaDKIhi4Dr/+JpHPnjchqS4VaMB8gEIrDpeSYNlhrj1oAI/8GwgqZ8UR4sZGxNpIzUg+XGJSYz5/cAB3P18ENSQvOwaNefJa7qIVNjMD7YwXKmfX9cyr5RHM5sibq/S5fHH/N7pig+aveTquGGVxInJr1IEDiyr2TsFARjPitp9KJSFLHLsA2jm1cZfNW0/d6ii+51HdLPKorHom3fPjb0jkIe1LPa9CrrjnfSrAE9a/w4qpSnDv7OjAzkieepz+VQCtpQGIzQxJcHWaFX32iZ6RQ6pmKc/22E0OZwsNM2FHrB5V1b+rfczl8Ej7/R1wAOtHWkbLbfwZ9Ux2N0N0EKW8r8cOjEbsxmN8FFQubTwl68uqjJLhEtrOUbM28JM/NkX+Ue1KRw+NJAdMFEZQKPb/b/X6s3nwPD4/4yLyUDCGyr8aGpzSBD5uIu5uSJNiWdNDjcnXtJJ6TlGGZqj91r7FckjA8FuSA6S3yA8epMNG3FTUxPVE=
24
+ on_success: always
25
+ on_failure: onchange
26
+ on_start: never
@@ -0,0 +1,51 @@
1
+ # LaserCutter versus BoxMaker
2
+
3
+ Another developer [Rahulbot](https://github.com/rahulbot/) created a similar app [BoxMaker](https://github.com/rahulbot/boxmaker/) in Java, which was an inspiration to LaserCutter.
4
+
5
+ Laser-Cutter library attempts to further advance the concept of programmatically creating
6
+ laser-cut box designs, provides additional fine tuning, many more options, strategies and most
7
+ importantly – extensibility.
8
+
9
+ Unlike `BoxMaker` this gem has a suit of automated tests (rspecs) around the core functionality.
10
+ In addition, new feature contributions are highly encouraged, and in that
11
+ regard having existing test suit offers confidence against regressions, and thus welcomes colaboration.
12
+
13
+ Finally, BoxMaker's notch-drawing algorithm generates non-symmetric and sometimes purely broken designs
14
+ (see picture below).
15
+
16
+ `laser-cutter`'s algorithm will create a _symmetric design for most panels_, but it might sacrifice
17
+ identical notch length. Depending on the box dimensions you may end up with a slightly different notch
18
+ length on each side of the box.
19
+
20
+ The choice ultimately comes down to the preference and feature set, so here I show you two boxes made with
21
+ each program, so you can pick what you prefer.
22
+
23
+ ### Example Outputs
24
+
25
+ Below are two examples of boxes with identical dimensions produced with `laser-cutter` and `boxmaker`:
26
+
27
+ This is how you would make a box with Adam Phelp's fork of BoxMaker (which adds flags and a lot of
28
+ niceties):
29
+
30
+ ```bash
31
+ git clone https://github.com/aphelps/boxmaker && cd boxmaker && ant
32
+ java -cp BOX.jar com.rahulbotics.boxmaker.BoxMaker \
33
+ -W 1 -H 2 -D 1.5 -T 0.125 -n 0.125 -o box.pdf
34
+ ```
35
+
36
+ And laser-cutter:
37
+
38
+ ```bash
39
+ gem install laser-cutter
40
+ laser-cutter -z 1x1.5x2/0.125/0.125 -O -o box.pdf
41
+ ```
42
+
43
+ ![LaserCutter Comparison](docs/comparison.jpg).
44
+
45
+ ## Contributing
46
+
47
+ 1. Fork it ( https://github.com/kigster/laser-cutter/fork )
48
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
49
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
50
+ 4. Push to the branch (`git push origin my-new-feature`)
51
+ 5. Create a new Pull Request
data/README.md CHANGED
@@ -1,34 +1,27 @@
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
- [![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)
3
+ [![Maintainability](https://api.codeclimate.com/v1/badges/bea3225fd93ee84d078a/maintainability)](https://codeclimate.com/github/kigster/laser-cutter/maintainability)[![Test Coverage](https://api.codeclimate.com/v1/badges/bea3225fd93ee84d078a/test_coverage)](https://codeclimate.com/github/kigster/laser-cutter/test_coverage)
5
4
 
6
- ## LaserCutter and Make-A-Box.io
5
+ [![Join the chat at https://gitter.im/kigster/laser-cutter](https://badges.gitter.im/kigster/laser-cutter.svg)](https://gitter.im/kigster/laser-cutter?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
6
+ [![GitHub issues](https://img.shields.io/github/issues/kigster/laser-cutter.svg)](https://github.com/kigster/laser-cutter/issues)
7
+ [![GitHub forks](https://img.shields.io/github/forks/kigster/laser-cutter.svg)](https://github.com/kigster/laser-cutter/network)
8
+ [![GitHub stars](https://img.shields.io/github/stars/kigster/laser-cutter.svg)](https://github.com/kigster/laser-cutter/stargazers)
9
+ [![GitHub license](https://img.shields.io/github/license/kigster/laser-cutter.svg)](https://github.com/kigster/laser-cutter/blob/master/LICENSE)
7
10
 
8
- ```laser-cutter``` is a ruby library for generating PDF designs for boxes of
9
- custom dimensions that suit your project, that can be cut from wood or acrylic
10
- using a laser-cutter. The sides of the box snap together using alternating notches,
11
- that are deliberately layed out in a symmetric form.
11
+ [![Donate](https://www.paypalobjects.com/en_US/i/btn/btn_donate_SM.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=FSFYYNEQ8RKWU)
12
12
 
13
- To use ```laser-cutter``` you need to have a recent version of ruby interpreter,
14
- install it as a gem, and use command line to generate PDFs.
13
+ # LaserCutter
15
14
 
16
- [Make-A-Box](http://makeabox.io) is a online web application that uses ```laser-cutter``` library
17
- and provides a straight-forward user interface for generating PDF designs without the need to install
18
- the gem or use command line.
15
+ **LaserCutter** is a ruby library for generating PDF designs for boxes of custom dimensions that suit your project, that are meant to be used as a cut template on a laser-cutter. The sides of the box snap together using alternating notches, that are deliberately laid out in a symmetric form.
19
16
 
20
- Use whatever suites you better.
17
+ To use `laser-cutter` you need to have a recent version of ruby interpreter, install it as a gem, and use command line to generate PDFs.
18
+
19
+ [MakeABox.IO](http://makeabox.io) is an online web application that uses `laser-cutter` library and provides a straight-forward user interface for generating PDF designs without the need to install the gem or use command line.
21
20
 
22
- ### Design Goals
21
+ Use whatever suites you better.
23
22
 
24
- One of the design goals of this project is to provide a highly extensible platform for creating
25
- laser-cut designs, where alternative strategies can be added over time, and supported by various
26
- command line options, and perhaps a light weight web application. If you are interested in
27
- contributing to the project, please see [contributing](CONTRIBUTING.md) for more details.
23
+ > NOTE: Please read our [feature comparison guide](BOXMAKER.md) of LaserCutter against an older tool called [BoxMaker](https://github.com/rahulbot/boxmaker).
28
24
 
29
- ```laser-cutter``` supports many flexible command line options that allow setting dimensions,
30
- stroke width, page size, layout, margins, padding (spacing between the boxes), and many more.
31
-
32
25
  ## Dependencies
33
26
 
34
27
  The gem depends primarily on [Prawn](http://prawnpdf.org) – a fantastic PDF generation library.
@@ -43,12 +36,49 @@ And then execute:
43
36
 
44
37
  $ bundle
45
38
 
46
- Or install it yourself as:
39
+ Or install it manually:
47
40
 
48
41
  $ gem install laser-cutter
49
42
 
50
43
  ## Usage
51
44
 
45
+ We'll start with some examples:
46
+
47
+ ### Examples
48
+
49
+ Create a box defined in inches, with kerf (cut width) set to `0.005in`, and open PDF in preview right after:
50
+
51
+ ```bash
52
+ laser-cutter -z 3x2x2/0.125 -k 0.005 -O -o box.pdf
53
+ ```
54
+
55
+ Create a box defined in millimeters, print verbose info, and set page size to A3, and layout to landscape, and stroke width to `1/2mm`:
56
+
57
+ ```bash
58
+ laser-cutter -u mm -w70 -h20 -d50 -t4.3 -n5 -iA3 -l landscape -s0.5 -v -O -o box.pdf
59
+ ```
60
+
61
+ List all possible page sizes in metric system:
62
+
63
+ ```bash
64
+ laser-cutter -L -u mm
65
+ ```
66
+
67
+ Create a box with provided dimensions, and save the config to a file for later use:
68
+
69
+ ```bash
70
+ laser-cutter -z 1.1x2.5x1.5/0.125/0.125 -p 0.1 -O -o box.pdf -W box-settings.json
71
+ ```
72
+
73
+ Read settings from a previously saved file:
74
+
75
+ ```bash
76
+ laser-cutter -O -o box.pdf -R box-settings.json
77
+ cat box-settings.json | laser-cutter -O -o box.pdf -R -
78
+ ```
79
+
80
+ ### Complete Help
81
+
52
82
  ```bash
53
83
 
54
84
  Usage: laser-cutter [options] -o filename.pdf
@@ -60,7 +90,7 @@ Specific Options:
60
90
  -d, --depth DEPTH Internal depth of the box
61
91
  -t, --thickness THICKNESS Thickness of the box material
62
92
  -n, --notch NOTCH Optional notch length (aka "tab width"), guide only
63
- -k, --kerf KERF Kerf - cut width (default is 0.007in)
93
+ -k, --kerf KERF Kerf - cut width (default is 0.0024in)
64
94
 
65
95
  -m, --margin MARGIN Margins from the edge of the document
66
96
  -p, --padding PADDING Space between the boxes on the page
@@ -90,41 +120,7 @@ Common Options:
90
120
  -u, --units UNITS Either 'in' for inches (default) or 'mm'
91
121
  ```
92
122
 
93
- ### Examples
94
-
95
- Create a box defined in inches, with kerf (cut width) set to 0.008", and open PDF in preview right after:
96
-
97
- ```bash
98
- laser-cutter -z 3x2x2/0.125 -k 0.008 -O -o box.pdf
99
- ```
100
-
101
- Create a box defined in millimeters, print verbose info, and set
102
- page size to A3, and layout to landscape, and stroke width to 1/2mm:
103
-
104
- ```bash
105
- laser-cutter -u mm -w70 -h20 -d50 -t4.3 -n5 -iA3 -l landscape -s0.5 -v -O -o box.pdf
106
- ```
107
-
108
- List all possible page sizes in metric system:
109
-
110
- ```bash
111
- laser-cutter -L -u mm
112
- ```
113
-
114
- Create a box with provided dimensions, and save the config to a file for later use:
115
-
116
- ```bash
117
- laser-cutter -z 1.1x2.5x1.5/0.125/0.125 -p 0.1 -O -o box.pdf -W box-settings.json
118
- ```
119
-
120
- Read settings from a previously saved file:
121
-
122
- ```bash
123
- laser-cutter -O -o box.pdf -R box-settings.json
124
- cat box-settings.json | laser-cutter -O -o box.pdf -R -
125
- ```
126
-
127
- ## Feature Wish List
123
+ ## Wish List
128
124
 
129
125
  * Create T-style joins, using various standard sizes of nuts and bolts (such as common #4-40 and M2 sizes)
130
126
  * Extensibility with various layout strategies, notch drawing strategies, basically plug and play
@@ -133,56 +129,9 @@ Read settings from a previously saved file:
133
129
  * Supporting lids and front panels, that are larger than the box itself and have holes for notches.
134
130
  * Your brilliant idea can be here too! Please see [contributing](CONTRIBUTING.md) for more info.
135
131
 
136
- ## LaserCutter vs BoxMaker
137
-
138
- [Rahulbot](https://github.com/rahulbot/)-made [BoxMaker](https://github.com/rahulbot/boxmaker/) is a
139
- functional generator of notched designs, similar to ```laser-cutter```, and generously open sourced
140
- by the author, and so in no way this project disputes BoxMaker's viability. In fact BoxMaker was an
141
- inspiration for this project.
142
-
143
- Laser-Cutter library attempts to further advance the concept of programmatically creating
144
- laser-cut box designs, provides additional fine tuning, many more options, strategies and most
145
- importantly – extensibility.
146
-
147
- Unlike ```BoxMaker```, this gem has a suit of automated tests (rspecs) around the core functionality.
148
- In addition, new feature contributions are highly encouraged, and in that
149
- regard having existing test suit offers confidence against regressions, and thus welcomes colaboration.
150
-
151
- Finally, BoxMaker's notch-drawing algorithm generates non-symmetric and sometimes purely broken designs
152
- (see picture below).
153
-
154
- ```laser-cutter```'s algorithm will create a _symmetric design for most panels_, but it might sacrifice
155
- identical notch length. Depending on the box dimensions you may end up with a slightly different notch
156
- length on each side of the box.
157
-
158
- The choice ultimately comes down to the preference and feature set, so here I show you two boxes made with
159
- each program, so you can pick what you prefer.
160
-
161
- ### Example Outputs
162
-
163
- Below are two examples of boxes with identical dimensions produced with ```laser-cutter``` and ```boxmaker```:
164
-
165
- This is how you would make a box with Adam Phelp's fork of BoxMaker (which adds flags and a lot of
166
- niceties):
167
-
168
- ```bash
169
- git clone https://github.com/aphelps/boxmaker && cd boxmaker && ant
170
- java -cp BOX.jar com.rahulbotics.boxmaker.BoxMaker \
171
- -W 1 -H 2 -D 1.5 -T 0.125 -n 0.125 -o box.pdf
172
- ```
173
-
174
- And laser-cutter:
175
-
176
- ```bash
177
- gem install laser-cutter
178
- laser-cutter -z 1x1.5x2/0.125/0.125 -O -o box.pdf
179
- ```
180
-
181
- ![LaserCutter Comparison](doc/comparison.jpg).
182
-
183
132
  ## Contributing
184
133
 
185
- 1. Fork it ( https://github.com/[my-github-username]/laser-cutter/fork )
134
+ 1. Fork it ( https://github.com/kigster/laser-cutter/fork )
186
135
  2. Create your feature branch (`git checkout -b my-new-feature`)
187
136
  3. Commit your changes (`git commit -am 'Add some feature'`)
188
137
  4. Push to the branch (`git push origin my-new-feature`)
data/Rakefile CHANGED
@@ -1,2 +1,29 @@
1
- require "bundler/gem_tasks"
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+ require 'yard'
2
4
 
5
+ def shell(*args)
6
+ puts "running: #{args.join(' ')}"
7
+ system(args.join(' '))
8
+ end
9
+
10
+ task :clean do
11
+ shell('rm -rf pkg/ tmp/ coverage/' )
12
+ end
13
+
14
+ task :permissions => [ :clean ] do
15
+ shell("chmod -v o+r,g+r * */* */*/* */*/*/* */*/*/*/* */*/*/*/*/*")
16
+ shell("find . -type d -exec chmod o+x,g+x {} \\;")
17
+ end
18
+
19
+ task :build => :permissions
20
+
21
+ YARD::Rake::YardocTask.new(:doc) do |t|
22
+ t.files = %w(lib/**/*.rb bin/* - README.md LICENSE.txt BOXMAKER.md)
23
+ t.options.unshift('--title','LaserCutter Library')
24
+ t.after = ->() { exec('open doc/index.html') }
25
+ end
26
+
27
+ RSpec::Core::RakeTask.new(:spec)
28
+
29
+ task :default => :spec
File without changes
@@ -22,9 +22,9 @@ Gem::Specification.new do |spec|
22
22
  spec.add_dependency 'hashie'
23
23
  spec.add_dependency 'colored'
24
24
 
25
- spec.add_development_dependency 'bundler', "~> 1.6"
25
+ spec.add_development_dependency 'yard'
26
+ spec.add_development_dependency 'simplecov'
27
+ spec.add_development_dependency 'bundler'
26
28
  spec.add_development_dependency 'rake'
27
29
  spec.add_development_dependency 'rspec'
28
- spec.add_development_dependency 'rspec-legacy_formatters'
29
- spec.add_development_dependency 'codeclimate-test-reporter'
30
30
  end
@@ -1,9 +1,10 @@
1
+ require 'forwardable'
1
2
  module Laser
2
3
  module Cutter
3
- # Note: this class badly needs refactoring and tests. Both are coming.
4
-
5
4
  class Box
6
5
  # Everything is in millimeters
6
+ extend Forwardable
7
+ def_delegators :@dim, :w, :h, :d
7
8
 
8
9
  attr_accessor :dim, :thickness, :notch_width, :kerf
9
10
  attr_accessor :padding, :units, :inside_box
@@ -13,33 +14,43 @@ module Laser
13
14
  attr_accessor :metadata, :notches
14
15
 
15
16
  def initialize(config = {})
16
- self.dim = Geometry::Dimensions.new(config['width'], config['height'], config['depth'])
17
+ self.dim = Geometry::Dimensions.new(config['width'], config['height'], config['depth'])
17
18
  self.thickness = config['thickness']
18
19
 
19
20
  self.notch_width = config['notch'] || (1.0 * self.longest / 5.0)
20
- self.kerf = config['kerf'] || 0.0
21
- self.padding = config['padding']
22
- self.units = config['units']
23
- self.inside_box = config['inside_box']
21
+ self.kerf = config['kerf'] || 0.0
22
+ self.padding = config['padding']
23
+ self.units = config['units']
24
+ self.inside_box = config['inside_box']
24
25
 
25
26
  self.notches = []
26
27
 
27
28
  self.metadata = Geometry::Point[config['metadata_width'] || 0, config['metadata_height'] || 0]
28
29
 
29
30
  create_faces! # generates dimensions for each side
30
- self.faces = [top, front, bottom, back, left, right]
31
-
32
- self.conf = {
33
- valign: [ :out, :out, :out, :out, :in, :in],
34
- halign: [ :in, :out, :in, :out, :in, :in],
35
- corners: {
36
- front: [ :no, :yes, :no, :yes, :no, :no], # our default choice, but may not work
37
- top: [ :yes, :no, :yes, :no, :no, :no] # 2nd choice, has to work if 1st doesn't
38
- },
31
+ self.faces = [top, front, bottom, back, left, right]
32
+
33
+ self.conf = {
34
+ valign: [:out, :out, :out, :out, :in, :in],
35
+ halign: [:in, :out, :in, :out, :in, :in],
36
+ corners: {
37
+ top: [:yes, :no, :yes, :no, :no, :no], # 2nd choice, has to work if 1st doesn't
38
+ front: [:no, :yes, :no, :yes, :no, :no], # our default choice, but may not work
39
+ },
39
40
  }
40
41
  self
41
42
  end
42
43
 
44
+ def generate_notches
45
+ position_faces!
46
+ self.corner_face = pick_corners_face
47
+ self.notches = []
48
+ faces.each_with_index do |face, face_index|
49
+ create_face_edges(face, face_index)
50
+ end
51
+ self.notches.flatten!
52
+ end
53
+
43
54
  def enclosure
44
55
  generate_notches if self.notches.empty?
45
56
  p1 = notches.first.p1.to_a
@@ -47,55 +58,15 @@ module Laser
47
58
 
48
59
  notches.each do |notch|
49
60
  n = notch.normalized
50
- n.p1.to_a.each_with_index {|c, i| p1[i] = c if c < p1[i] }
51
- n.p2.to_a.each_with_index {|c, i| p2[i] = c if c > p2[i] }
61
+ n.p1.to_a.each_with_index {|c, i| p1[i] = c if c < p1[i]}
62
+ n.p2.to_a.each_with_index {|c, i| p2[i] = c if c > p2[i]}
52
63
  end
53
64
 
54
65
  Geometry::Rect[Geometry::Point.new(p1), Geometry::Point.new(p2)]
55
66
  end
56
67
 
57
- def generate_notches
58
- position_faces!
59
- corner_face = pick_corners_face
60
- self.notches = []
61
- faces.each_with_index do |face, face_index|
62
- bound = face_bounding_rect(face)
63
- side_lines = []
64
- edges = []
65
- bound.sides.each_with_index do |bounding_side, side_index |
66
- include_corners = (self.conf[:corners][corner_face][face_index] == :yes && side_index.odd?)
67
- key = side_index.odd? ? :valign : :halign
68
- center_out = (self.conf[key][face_index] == :out)
69
- edges << Notching::Edge.new(bounding_side, face.sides[side_index],
70
- {:notch_width => notch_width,
71
- :thickness => thickness,
72
- :kerf => kerf,
73
- :center_out => center_out,
74
- :corners => include_corners
75
- })
76
- end
77
-
78
- if edges.any?{|e| e.corners} && !edges.all?{|e| e.first_notch_out? }
79
- edges.each {|e| e.adjust_corners = true }
80
- end
81
-
82
- edges.each do |edge|
83
- side_lines << Notching::PathGenerator.new(edge).generate
84
- end
85
-
86
- aggregator = Aggregator.new(side_lines.flatten)
87
- aggregator.dedup!.deoverlap!.dedup!
88
- self.notches << aggregator.lines
89
- end
90
- self.notches.flatten!
91
- end
92
-
93
- def w; dim.w; end
94
- def h; dim.h; end
95
- def d; dim.d; end
96
-
97
68
  def longest
98
- [w, h, d].max()
69
+ [w, h, d].max
99
70
  end
100
71
 
101
72
  def to_s
@@ -104,6 +75,37 @@ module Laser
104
75
 
105
76
  private
106
77
 
78
+ def create_face_edges(face, face_index)
79
+ bound = face_bounding_rect(face)
80
+
81
+ side_lines = []
82
+ edges = []
83
+ bound.sides.each_with_index do |bounding_side, side_index|
84
+ include_corners = (self.conf[:corners][corner_face][face_index] == :yes && side_index.odd?)
85
+ key = side_index.odd? ? :valign : :halign
86
+ center_out = (self.conf[key][face_index] == :out)
87
+ edges << Notching::Edge.new(bounding_side, face.sides[side_index],
88
+ { :notch_width => notch_width,
89
+ :thickness => thickness,
90
+ :kerf => kerf,
91
+ :center_out => center_out,
92
+ :corners => include_corners
93
+ })
94
+ end
95
+
96
+ if edges.any? {|e| e.corners} && !edges.all? {|e| e.first_notch_out?}
97
+ edges.each {|e| e.adjust_corners = true}
98
+ end
99
+
100
+ edges.each do |edge|
101
+ side_lines << Notching::PathGenerator.new(edge).generate
102
+ end
103
+
104
+ aggregator = Aggregator.new(side_lines.flatten)
105
+ aggregator.dedup!.deoverlap!.dedup!
106
+ self.notches << aggregator.lines
107
+ end
108
+
107
109
  def face_bounding_rect(face)
108
110
  b = face.clone
109
111
  b.move_to(b.position.plus(-thickness, -thickness))
@@ -141,39 +143,39 @@ module Laser
141
143
  left.x = offset_x - d - 2 * thickness - padding
142
144
  right.x = offset_x + w + 2 * thickness + padding
143
145
 
144
- [bottom, front, top, back].each { |s| s.x = offset_x }
146
+ [bottom, front, top, back].each {|s| s.x = offset_x}
145
147
 
146
148
  # Y Coordinate
147
149
  top.y = offset_y - d - 2 * thickness - padding
148
150
  bottom.y = offset_y + h + 2 * thickness + padding
149
151
  back.y = bottom.y + d + 2 * thickness + padding
150
152
 
151
- [left, front, right].each { |s| s.y = offset_y }
153
+ [left, front, right].each {|s| s.y = offset_y}
152
154
 
153
155
  faces.each(&:relocate!)
154
156
  end
155
157
 
156
158
  def create_faces!
157
- zero = Geometry::Point.new(0, 0)
159
+ zero = Geometry::Point.new(0, 0)
158
160
  self.front = Geometry::Rect.create(zero, dim.w, dim.h, "front")
159
- self.back = Geometry::Rect.create(zero, dim.w, dim.h, "back")
161
+ self.back = Geometry::Rect.create(zero, dim.w, dim.h, "back")
160
162
 
161
- self.top = Geometry::Rect.create(zero, dim.w, dim.d, "top")
163
+ self.top = Geometry::Rect.create(zero, dim.w, dim.d, "top")
162
164
  self.bottom = Geometry::Rect.create(zero, dim.w, dim.d, "bottom")
163
165
 
164
- self.left = Geometry::Rect.create(zero, dim.d, dim.h, "left")
166
+ self.left = Geometry::Rect.create(zero, dim.d, dim.h, "left")
165
167
  self.right = Geometry::Rect.create(zero, dim.d, dim.h, "right")
166
168
  end
167
169
 
168
170
  # Choose which face will be responsible for filling out the little square overlap
169
171
  # in the corners. Only one of the 3 possible sides need to be picked.
170
172
  def pick_corners_face
171
- b = face_bounding_rect(front)
173
+ b = face_bounding_rect(front)
172
174
  edges = []
173
175
  front.sides[0..1].each_with_index do |face, index|
174
- edges << Notching::Edge.new(b.sides[index], face, :notch_width => notch_width, :kerf => kerf )
176
+ edges << Notching::Edge.new(b.sides[index], face, :notch_width => notch_width, :kerf => kerf)
175
177
  end
176
- edges.map(&:notch_count).all?{|c| c % 4 == 3} ? :top : :front
178
+ edges.map(&:notch_count).all? {|c| c % 4 == 3} ? :top : :front
177
179
  end
178
180
 
179
181
  end
@@ -0,0 +1,18 @@
1
+ require 'forwardable'
2
+ module Laser
3
+ module Cutter
4
+ # Note: this class badly needs refactoring and tests. Both are coming.
5
+
6
+
7
+ class Face
8
+ attr_accessor :edges, :rect
9
+ extend Forwardable
10
+ def_delegators :@rect, *((Geometry::Rect.new(Geometry::Point.new(0,0), Geometry::Point.new(1,1))).methods - Object.methods)
11
+ def initialize(rect, edges = [])
12
+ self.rect = rect
13
+ self.edges = edges
14
+ end
15
+ end
16
+
17
+ end
18
+ end
@@ -5,6 +5,5 @@ module Laser
5
5
  end
6
6
  end
7
7
 
8
- require_relative 'notching/base'
9
8
  require_relative 'notching/edge'
10
9
  require_relative 'notching/path_generator'
@@ -32,8 +32,8 @@ module Laser
32
32
  self.notch_width = options[:notch_width]
33
33
  self.adjust_corners = options[:adjust_corners]
34
34
 
35
- adjust_for_kerf!
36
35
  calculate_notch_width!
36
+ adjust_for_kerf!
37
37
  end
38
38
 
39
39
  def adjust_for_kerf!
@@ -68,11 +68,11 @@ module Laser
68
68
  private
69
69
 
70
70
  def calculate_notch_width!
71
- length = kerf? ? self.inside.length - kerf : self.inside.length
72
- count = (length / notch_width).to_f.ceil + 1
71
+ count = ((self.inside.length) / notch_width).to_f.ceil + 1
73
72
  count = (count / 2 * 2) + 1 # make count always an odd number
74
73
  count = [MINIMUM_NOTCHES_PER_SIDE, count].max
75
- self.notch_width = 1.0 * length / count
74
+
75
+ self.notch_width = 1.0 * (self.inside.length) / count
76
76
  self.notch_count = count
77
77
  end
78
78
 
@@ -32,6 +32,17 @@ module Laser
32
32
  end
33
33
  end
34
34
 
35
+ # One of the key "tricks" that this algorithm applies, is that it converts everything into
36
+ # pure set of lines in the end. It then tries to find all intersections of the lines so that
37
+ # we can remove duplicates. So any segment of any line that is covered by 2 lines or more is removed,
38
+ # cleared completely for an empty space. This turns out to be very useful indeed, because we can
39
+ # paint with wide brush strokes to get the carcass, and then fine tune it by adding or removing line
40
+ # segments. Some of the lines below are added to actually remove the lines that might have otherwise
41
+ # been there.
42
+ #
43
+ # This comes especially handy when drawing corner boxes, which are deliberately made not to match the notch
44
+ # width, but to match thickness of the material. The corner notces for these sides will therefore have
45
+ # length equal to the thickness + regular notch length.
35
46
  class PathGenerator
36
47
 
37
48
  extend ::Forwardable
@@ -84,81 +95,23 @@ module Laser
84
95
  end
85
96
  end
86
97
 
98
+ # These two boxes occupy the corners of the 3D box. They do not match
99
+ # in width to our notches because they are usually merged with them. Their
100
+ # size is equal to the thickness of the material (adjusted for kerf)
101
+ # It's just an aesthetic choice I guess.
87
102
  def corner_box_sides
88
103
  boxes = []
89
104
  extra_lines = []
90
- sides = []
91
105
 
92
- # These two boxes occupy the corners of the 3D box. They do not match
93
- # in width to our notches because they are usually merged with them.
94
- # It's just an aesthetic choice I guess.
95
106
  boxes << Geometry::Rect[edge.inside.p1.clone, edge.outside.p1.clone]
96
107
  boxes << Geometry::Rect[edge.inside.p2.clone, edge.outside.p2.clone]
97
108
 
98
- if kerf?
99
- if adjust_corners
100
- if first_notch_out?
101
- k = 2
102
- direction = -1
103
- dim_index = 1
104
- extra_lines << add_corners_when_out(dim_index, direction, k)
105
- else
106
- k = -2
107
- direction = 1
108
- dim_index = 0
109
- extra_lines << add_boxes_when_in(dim_index, direction, k)
110
- end
111
- end
112
- end
109
+ extra_lines << add_corners if adjust_corners && kerf?
113
110
  sides = boxes.flatten.map(&:relocate!).map(&:sides)
114
111
  sides << extra_lines if !extra_lines.empty?
115
112
  sides.flatten
116
113
  end
117
114
 
118
- def add_boxes_when_in(dim_index, direction, k)
119
- v1 = k * direction * shift_vector(1, dim_index)
120
- v2 = k * direction * shift_vector(2, dim_index)
121
- p1 = edge.inside.p1.plus(v1)
122
- coords = []
123
- coords[d_index_along] = edge.inside.p1[d_index_along]
124
- coords[d_index_across] = edge.outside.p1[d_index_across]
125
- p2 = Geometry::Point[*coords]
126
- r1 = Geometry::Rect[p1, p2]
127
-
128
- p1 = edge.inside.p2.plus(v2)
129
- coords = []
130
- coords[d_index_along] = edge.inside.p2[d_index_along]
131
- coords[d_index_across] = edge.outside.p2[d_index_across]
132
- p2 = Geometry::Point[*coords]
133
- r2 = Geometry::Rect[p1, p2]
134
- lines = [r1, r2].map(&:sides).flatten
135
- lines << Geometry::Line[edge.inside.p1.plus(v1), edge.inside.p1.clone]
136
- lines << Geometry::Line[edge.inside.p2.plus(v2), edge.inside.p2.clone]
137
- lines
138
- end
139
-
140
- def add_corners_when_out(dim_index, direction, k)
141
- v1 = direction * k * shift_vector(1, dim_index)
142
- v2 = direction * k * shift_vector(2, dim_index)
143
- p1 = edge.inside.p1.plus(v1)
144
- coords = []
145
- coords[d_index_along] = edge.outside.p1[d_index_along]
146
- coords[d_index_across] = edge.inside.p1[d_index_across]
147
- p2 = Geometry::Point[*coords]
148
- r1 = Geometry::Rect[p1, p2]
149
-
150
- p1 = edge.inside.p2.plus(v2)
151
- coords = []
152
- coords[d_index_along] = edge.outside.p2[d_index_along]
153
- coords[d_index_across] = edge.inside.p2[d_index_across]
154
- p2 = Geometry::Point[*coords]
155
- r2 = Geometry::Rect[p1, p2]
156
- lines = [r1, r2].map(&:sides).flatten
157
- lines << Geometry::Line[edge.inside.p1.plus(v1), edge.inside.p1.clone]
158
- lines << Geometry::Line[edge.inside.p2.plus(v2), edge.inside.p2.clone]
159
- lines
160
- end
161
-
162
115
  def shift_vector(index, dim_shift = 0)
163
116
  shift = []
164
117
  shift[(d_index_across + dim_shift) % 2] = 0
@@ -189,6 +142,38 @@ module Laser
189
142
  end
190
143
 
191
144
  private
145
+ # Helper method to calculate dimensions of our corners.
146
+ def add_corners
147
+ k, direction, dim_index, edge_along, edge_across = if first_notch_out?
148
+ [2, -1, 1, :inside, :outside]
149
+ else
150
+ [-2, 1, 0, :outside, :inside]
151
+ end
152
+ v1 = direction * k * shift_vector(1, dim_index)
153
+ v2 = direction * k * shift_vector(2, dim_index)
154
+
155
+ r1 = define_corner_rect(:p1, v1, edge_along, edge_across)
156
+ r2 = define_corner_rect(:p2, v2, edge_along, edge_across)
157
+
158
+ lines = [r1, r2].map(&:sides).flatten
159
+
160
+ # Our clever algorithm removes automatically duplicate lines. These lines
161
+ # below are added to actually clear out this space and remove the existing
162
+ # lines that are already there.
163
+ lines << Geometry::Line[edge.inside.p1.plus(v1), edge.inside.p1.clone]
164
+ lines << Geometry::Line[edge.inside.p2.plus(v2), edge.inside.p2.clone]
165
+ lines
166
+ end
167
+
168
+ def define_corner_rect(point, delta, edge_along, edge_across)
169
+ p1 = edge.inside.send(point).plus(delta)
170
+ coords = []
171
+ coords[d_index_along] = edge.send(edge_along).send(point)[d_index_along]
172
+ coords[d_index_across] = edge.send(edge_across).send(point)[d_index_across]
173
+ p2 = Geometry::Point[*coords]
174
+ Geometry::Rect[p1, p2]
175
+ end
176
+
192
177
 
193
178
  # This method has the bulk of the logic: we create the list of path deltas
194
179
  # to be applied when we walk the edge next.
@@ -1,5 +1,5 @@
1
1
  module Laser
2
2
  module Cutter
3
- VERSION = "1.0.3"
3
+ VERSION = '1.0.5'
4
4
  end
5
5
  end
@@ -34,7 +34,6 @@ module Laser
34
34
  expect(box2.enclosure.to_a.flatten.map(&:round)).to eql([0,0, 232, 317])
35
35
  end
36
36
  end
37
-
38
37
  end
39
38
  end
40
39
  end
@@ -5,16 +5,12 @@
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
-
13
8
  ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __FILE__)
14
9
  require 'rubygems'
15
10
  require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE'])
11
+ require 'simplecov'
12
+ SimpleCov.start
16
13
  require 'laser-cutter'
17
- require "codeclimate-test-reporter"
18
14
 
19
15
 
20
16
 
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: 1.0.3
4
+ version: 1.0.5
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-11-01 00:00:00.000000000 Z
11
+ date: 2018-01-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: prawn
@@ -53,21 +53,21 @@ dependencies:
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
- name: bundler
56
+ name: yard
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - "~>"
59
+ - - ">="
60
60
  - !ruby/object:Gem::Version
61
- version: '1.6'
61
+ version: '0'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - "~>"
66
+ - - ">="
67
67
  - !ruby/object:Gem::Version
68
- version: '1.6'
68
+ version: '0'
69
69
  - !ruby/object:Gem::Dependency
70
- name: rake
70
+ name: simplecov
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - ">="
@@ -81,7 +81,7 @@ dependencies:
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
83
  - !ruby/object:Gem::Dependency
84
- name: rspec
84
+ name: bundler
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
87
  - - ">="
@@ -95,7 +95,7 @@ dependencies:
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
97
  - !ruby/object:Gem::Dependency
98
- name: rspec-legacy_formatters
98
+ name: rake
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
101
  - - ">="
@@ -109,7 +109,7 @@ dependencies:
109
109
  - !ruby/object:Gem::Version
110
110
  version: '0'
111
111
  - !ruby/object:Gem::Dependency
112
- name: codeclimate-test-reporter
112
+ name: rspec
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
115
  - - ">="
@@ -136,6 +136,7 @@ files:
136
136
  - ".gitignore"
137
137
  - ".rspec"
138
138
  - ".travis.yml"
139
+ - BOXMAKER.md
139
140
  - CONTRIBUTING.md
140
141
  - Gemfile
141
142
  - LICENSE
@@ -143,7 +144,7 @@ files:
143
144
  - README.md
144
145
  - Rakefile
145
146
  - bin/laser-cutter
146
- - doc/comparison.jpg
147
+ - docs/comparison.jpg
147
148
  - laser-cutter.gemspec
148
149
  - lib/laser-cutter.rb
149
150
  - lib/laser-cutter/aggregator.rb
@@ -151,6 +152,7 @@ files:
151
152
  - lib/laser-cutter/cli/opt_parser.rb
152
153
  - lib/laser-cutter/cli/serializer.rb
153
154
  - lib/laser-cutter/configuration.rb
155
+ - lib/laser-cutter/face.rb
154
156
  - lib/laser-cutter/geometry.rb
155
157
  - lib/laser-cutter/geometry/dimensions.rb
156
158
  - lib/laser-cutter/geometry/point.rb
@@ -159,7 +161,6 @@ files:
159
161
  - lib/laser-cutter/geometry/shape/rect.rb
160
162
  - lib/laser-cutter/geometry/tuple.rb
161
163
  - lib/laser-cutter/notching.rb
162
- - lib/laser-cutter/notching/base.rb
163
164
  - lib/laser-cutter/notching/edge.rb
164
165
  - lib/laser-cutter/notching/path_generator.rb
165
166
  - lib/laser-cutter/page_manager.rb
@@ -203,7 +204,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
203
204
  version: '0'
204
205
  requirements: []
205
206
  rubyforge_project:
206
- rubygems_version: 2.2.2
207
+ rubygems_version: 2.6.11
207
208
  signing_key:
208
209
  specification_version: 4
209
210
  summary: Creates notched box outlines for laser-cut boxes which are geometrically
@@ -221,4 +222,3 @@ test_files:
221
222
  - spec/rect_spec.rb
222
223
  - spec/renderer_spec.rb
223
224
  - spec/spec_helper.rb
224
- has_rdoc:
@@ -1,13 +0,0 @@
1
- module Laser::Cutter::Notching
2
- class Base
3
- attr_accessor :edge
4
-
5
- def initialize(edge)
6
- @edge = edge
7
- end
8
-
9
- def notches
10
- raise 'Abstract method'
11
- end
12
- end
13
- end