jenncad 1.0.0.pre.alpha1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. checksums.yaml +7 -0
  2. data/Rakefile +1 -0
  3. data/bin/jenncad +10 -0
  4. data/examples/old/cube.rb +12 -0
  5. data/examples/old/slot.rb +10 -0
  6. data/examples/old/test.rb +18 -0
  7. data/examples/old/test1.rb +21 -0
  8. data/examples/old/test2.rb +9 -0
  9. data/examples/old/test3.rb +15 -0
  10. data/examples/old/test4.rb +17 -0
  11. data/examples/old/test5.rb +31 -0
  12. data/jenncad.gemspec +27 -0
  13. data/lib/jenncad/commands.rb +169 -0
  14. data/lib/jenncad/default_profile.rb +40 -0
  15. data/lib/jenncad/extras/din912.rb +89 -0
  16. data/lib/jenncad/extras/din933.rb +64 -0
  17. data/lib/jenncad/extras/din934.rb +99 -0
  18. data/lib/jenncad/extras/hardware.rb +16 -0
  19. data/lib/jenncad/extras/iso7380.rb +58 -0
  20. data/lib/jenncad/jenncad.rb +3 -0
  21. data/lib/jenncad/openscad.rb +274 -0
  22. data/lib/jenncad/part.rb +14 -0
  23. data/lib/jenncad/patches/array.rb +29 -0
  24. data/lib/jenncad/primitives/aggregation.rb +12 -0
  25. data/lib/jenncad/primitives/boolean_object.rb +76 -0
  26. data/lib/jenncad/primitives/circle.rb +11 -0
  27. data/lib/jenncad/primitives/cube.rb +69 -0
  28. data/lib/jenncad/primitives/cylinder.rb +52 -0
  29. data/lib/jenncad/primitives/hull_object.rb +4 -0
  30. data/lib/jenncad/primitives/intersection_object.rb +4 -0
  31. data/lib/jenncad/primitives/linear_extrude.rb +25 -0
  32. data/lib/jenncad/primitives/openscad_include.rb +11 -0
  33. data/lib/jenncad/primitives/polygon.rb +9 -0
  34. data/lib/jenncad/primitives/primitive.rb +24 -0
  35. data/lib/jenncad/primitives/projection.rb +9 -0
  36. data/lib/jenncad/primitives/rotate_extrude.rb +20 -0
  37. data/lib/jenncad/primitives/rounded_cube.rb +77 -0
  38. data/lib/jenncad/primitives/slot.rb +82 -0
  39. data/lib/jenncad/primitives/sphere.rb +11 -0
  40. data/lib/jenncad/primitives/subtract_object.rb +84 -0
  41. data/lib/jenncad/primitives/union_object.rb +5 -0
  42. data/lib/jenncad/profile_loader.rb +34 -0
  43. data/lib/jenncad/project.rb +28 -0
  44. data/lib/jenncad/register.rb +31 -0
  45. data/lib/jenncad/shortcuts.rb +109 -0
  46. data/lib/jenncad/thing.rb +308 -0
  47. data/lib/jenncad/transformation/color.rb +8 -0
  48. data/lib/jenncad/transformation/mirror.rb +7 -0
  49. data/lib/jenncad/transformation/move.rb +7 -0
  50. data/lib/jenncad/transformation/multmatrix.rb +9 -0
  51. data/lib/jenncad/transformation/rotate.rb +7 -0
  52. data/lib/jenncad/transformation/scale.rb +7 -0
  53. data/lib/jenncad/transformation/transformation.rb +14 -0
  54. data/lib/jenncad/version.rb +4 -0
  55. data/lib/jenncad.rb +73 -0
  56. data/todo.txt +29 -0
  57. metadata +155 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 81f68c07dc7fd50719d6ce024f56eb25712ef97c9b31568dcfa6658d9fa01596
4
+ data.tar.gz: 3c877488f386a7d7c6f8dd3b1543ca84641316ae2dbd5d6bcbb4577fbf94ae7c
5
+ SHA512:
6
+ metadata.gz: 9a95e7f398d275b81bfb4c9bbe21d3bd0e306708f0ef514e8391f50837eab066ec7aaca3ee46e4bbb08cd4a0c3fbee009b899b87aea2b5fe86ea5a74f6294ee3
7
+ data.tar.gz: 5425a1f502e12c8b8300995f921b2e9ce1d10f214728f5f2b6508610aa783f76907f3ffcc9bb40ed88e997302a12a896dc7afa9c544d6e3f0216750e4914e37f
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/bin/jenncad ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+ require "jenncad"
3
+
4
+ JennCad::Commands.register "", JennCad::Commands::Observe
5
+ JennCad::Commands.register "run", JennCad::Commands::Observe
6
+ JennCad::Commands.register "build", JennCad::Commands::Build
7
+ JennCad::Commands.register "new", JennCad::Commands::NewPart
8
+ JennCad::Commands.register "create", JennCad::Commands::NewProject
9
+
10
+ Hanami::CLI.new(JennCad::Commands).call
@@ -0,0 +1,12 @@
1
+ require 'rubygems'
2
+ require 'jenncad'
3
+ include JennCad
4
+
5
+ # cubes are centered in x,y and flat to z=0 by default
6
+ res = cube(40,30,20)
7
+ # if symbols are omitted first argument of cylinder is d (diameter), second is height
8
+ # if height is omitted, it will assume height of first suitable parent object. This only works for z direction
9
+ # if height is omitted, it will also reward you with automatic z-fighting. For other cuts it'll try to do the same but is not so smart
10
+ res -= cylinder(5)
11
+
12
+ res.openscad("cube.scad")
@@ -0,0 +1,10 @@
1
+ require 'rubygems'
2
+ require 'jenncad'
3
+ include JennCad
4
+
5
+ res = cube(30,30,10)
6
+
7
+ res -= slot(d:10, x:20, a:30).move(x:5)
8
+ res -= slot(d:10, x:20, a:-30).move(x:5)
9
+
10
+ res.openscad("slot.scad")
@@ -0,0 +1,18 @@
1
+ require 'jenncad'
2
+ include JennCad
3
+ include JennCad::Extras
4
+ Nut = Din934
5
+
6
+ res = cylinder(d:40,h:20)
7
+
8
+ n = Nut.new(4)
9
+ res -= n.cut
10
+
11
+ n = Nut.new(4)
12
+ res -= n.cut.translate(x:20)
13
+ res += n.show.translate(x:20)
14
+
15
+
16
+
17
+ a = OpenScad.new(res)
18
+ a.save("examples/test1.scad")
@@ -0,0 +1,21 @@
1
+ require 'rubygems'
2
+ require 'jenncad'
3
+ include JennCad
4
+ include JennCad::Extras
5
+ Nut = Din934
6
+
7
+ h1 = 10
8
+ h2 = 20
9
+ res = cube([10,20,h1])
10
+ res += cylinder(d:40,h:h2).move(z:h1)
11
+
12
+
13
+ n = Nut.new(4)
14
+ res -= n.cut
15
+
16
+ n = Nut.new(4)
17
+ res -= n.cut.move(z:h1+h2-n.height)
18
+
19
+
20
+
21
+ res.openscad("examples/test1.scad")
@@ -0,0 +1,9 @@
1
+ require 'jenncad'
2
+ include JennCad
3
+
4
+ res = import("involute_gears","bevel_gear",number_of_teeth:13, bore_diameter:10)
5
+ res += import("involute_gears","bevel_gear",number_of_teeth:6, bore_diameter:5).rotate(x:90).translate(y:50,z:30)
6
+
7
+
8
+ a = OpenScad.new(res)
9
+ a.save("examples/test2.scad")
@@ -0,0 +1,15 @@
1
+ require 'rubygems'
2
+ require 'jenncad'
3
+ include JennCad
4
+ include JennCad::Extras
5
+ Nut = Din934
6
+
7
+ res = cylinder(d:40,h:20)
8
+ res &= cylinder(d:40,h:20).translate(x:20)
9
+ res &= cube([20,20,20]).translate(y:20)
10
+
11
+ res.skew(y:-0.3)
12
+
13
+
14
+ a = OpenScad.new(res)
15
+ a.save("examples/test3.scad")
@@ -0,0 +1,17 @@
1
+ require 'rubygems'
2
+ require 'jenncad'
3
+ include JennCad
4
+ include JennCad::Extras
5
+ Nut = Din934
6
+
7
+ res = cube([30,30,10]).center_xy
8
+ res -= cylinder(d:20,h:2)
9
+
10
+ cyl = cylinder(d:10,h:5).translate(z:5)
11
+ res -= cyl
12
+
13
+ puts cyl.calc_z+cyl.calc_h
14
+
15
+
16
+ a = OpenScad.new(res)
17
+ a.save("examples/test4.scad")
@@ -0,0 +1,31 @@
1
+ require 'rubygems'
2
+ require 'jenncad'
3
+ include JennCad
4
+ include JennCad::Extras
5
+ Nut = Din934
6
+
7
+ res = cube([30,30,10]).center_xy
8
+ # at this moment, res is a cube
9
+ res.color = "Blue"
10
+
11
+ res += cylinder(d:10,h:20)
12
+ # with the += operator, res is now a union boolean object
13
+ res.color [120,20,13,200]
14
+
15
+ # everything added to the union will remain this color
16
+ res += cylinder(d:6,h:25)
17
+
18
+ # unless specified otherwise
19
+ res += cylinder(d:5, h:30).color("red")
20
+
21
+
22
+
23
+ # subtracting will change res to a subtraction object
24
+ res -= cylinder(d:4, h:30)
25
+ res += cylinder(d:2, h:40)
26
+ res.color("green")
27
+
28
+
29
+
30
+ a = OpenScad.new(res)
31
+ a.save("examples/test5.scad")
data/jenncad.gemspec ADDED
@@ -0,0 +1,27 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+
5
+ require "jenncad"
6
+
7
+ Gem::Specification.new do |gem|
8
+ gem.name = "jenncad"
9
+ gem.version = JennCad::VERSION
10
+ gem.authors = ["Jennifer Glauche"]
11
+ gem.email = ["=^.^=@jenncad.kittenme.ws"]
12
+ gem.homepage = ""
13
+ gem.summary = %q{TBD}
14
+ gem.description = %q{TBD}
15
+
16
+ gem.license = 'LGPL-3'
17
+ gem.files = `git ls-files`.split($/)
18
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
19
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
20
+ gem.require_paths = ["lib"]
21
+
22
+ gem.required_ruby_version = ">= 2.5.0"
23
+ gem.add_runtime_dependency "geo3d"
24
+ gem.add_runtime_dependency "deep_merge"
25
+ gem.add_runtime_dependency "hanami-cli"
26
+ gem.add_runtime_dependency "activesupport"
27
+ end
@@ -0,0 +1,169 @@
1
+ module JennCad
2
+ module Commands
3
+ extend Hanami::CLI::Registry
4
+
5
+ class Run < Hanami::CLI::Command
6
+ argument :name, required: false
7
+
8
+ def guess_executable(dir=Dir.pwd)
9
+ dir.split("/").last.to_s + ".rb"
10
+ end
11
+
12
+ def check_executable(file)
13
+ return true if File.exists?(file)
14
+ # this is not too smart at the moment
15
+ puts "cannot find executable #{file}"
16
+ nil
17
+ end
18
+
19
+ def observe(exec)
20
+ execute(exec)
21
+ script = Observr::Script.new
22
+ Dir.glob("**/**.rb").each do |file|
23
+ script.watch(file) do
24
+ execute(exec)
25
+ end
26
+ end
27
+ contr = Observr::Controller.new(script, Observr.handler.new)
28
+ puts "JennCad running, refreshing on file changes. Press ctrl+c to exit"
29
+ contr.run
30
+ end
31
+
32
+ def execute(file)
33
+ print "refreshing..."
34
+ r = system("./#{file}")
35
+ case r
36
+ when true
37
+ $jenncad_profile.on_success(file)
38
+ when false
39
+ $jenncad_profile.on_error(file)
40
+ end
41
+ end
42
+
43
+ def build
44
+ admesh_installed = system("admesh --version > /dev/null")
45
+ unless admesh_installed
46
+ puts "Warning: cannot find admesh, stl export will be in ASCII"
47
+ end
48
+
49
+ Dir.glob("output/**/*.scad").each do |file|
50
+ stl = file.gsub(".scad",".stl")
51
+ build_stl(file, stl)
52
+ convert_to_binary(stl) if admesh_installed
53
+ end
54
+ end
55
+
56
+ def build_stl(scad, stl)
57
+ puts "building #{stl}"
58
+ system("openscad #{scad} -o #{stl}")
59
+ end
60
+
61
+ def convert_to_binary(stl)
62
+ system("admesh #{stl} -b #{stl}")
63
+ end
64
+
65
+ end
66
+
67
+ class Build < Run
68
+ def call(name: nil, **)
69
+ unless name
70
+ name = guess_executable
71
+ end
72
+ if check_executable(name)
73
+ execute(name)
74
+ build
75
+ end
76
+ end
77
+ end
78
+
79
+ class Observe < Run
80
+ def call(name: nil, **)
81
+ unless name
82
+ name = guess_executable
83
+ end
84
+ if check_executable(name)
85
+ observe(name)
86
+ end
87
+ end
88
+ end
89
+
90
+ class NewPart < Hanami::CLI::Command
91
+ include ActiveSupport::Inflector
92
+ desc "creates a new part in a project"
93
+ argument :name, required: true
94
+ def call(name:, **)
95
+ dir = Dir.pwd.split("/").last
96
+ executable = underscore(dir)+".rb"
97
+ executable_class = camelize(dir)
98
+ unless File.exists?(executable)
99
+ puts "Could not find #{executable}. Are you in a JennCad project directory?"
100
+ exit
101
+ end
102
+ FileUtils.mkdir_p("parts")
103
+ name = underscore(name)
104
+ classname = camelize(name)
105
+ filename = "parts/#{name}.rb"
106
+ if File.exists?(filename)
107
+ puts "File #{filename} already exists."
108
+ exit
109
+ end
110
+ File.open(filename, "w") do |f|
111
+ f.puts "class #{classname} < Part"
112
+ f.puts " def initialize(opts={})"
113
+ f.puts " @opts = {"
114
+ f.puts " x: 10,"
115
+ f.puts " y: 10,"
116
+ f.puts " z: 5,"
117
+ f.puts " }.merge(opts)"
118
+ f.puts " end"
119
+ f.puts ""
120
+ f.puts " def part"
121
+ f.puts " cube(@opts)"
122
+ f.puts " end"
123
+ f.puts "end"
124
+ end
125
+ puts "part #{filename} created. In your #{executable} add to class #{executable_class}:"
126
+ puts " def #{name}"
127
+ puts " #{classname}.new(config)"
128
+ puts " end"
129
+
130
+ end
131
+
132
+ end
133
+
134
+ class NewProject < Hanami::CLI::Command
135
+ include ActiveSupport::Inflector
136
+ desc "generates a new project"
137
+ argument :name, required: true
138
+
139
+ def call(name:, **)
140
+ name = underscore(name)
141
+ filename = name+".rb"
142
+ Dir.mkdir(name)
143
+ Dir.chdir(name)
144
+ classname = camelize(name)
145
+ File.open(filename, "w") do |f|
146
+ f.puts "#!/usr/bin/env ruby"
147
+ f.puts "require \"jenncad\""
148
+ f.puts "include JennCad"
149
+ f.puts ""
150
+ f.puts "class #{classname} < Project"
151
+ f.puts " def config"
152
+ f.puts " {}"
153
+ f.puts " end"
154
+ f.puts ""
155
+ f.puts " def #{name}"
156
+ f.puts " cube(10,10,10)"
157
+ f.puts " end"
158
+ f.puts "end"
159
+ f.puts ""
160
+ f.puts "#{classname}.new.run"
161
+ end
162
+ File.chmod(0755, filename)
163
+
164
+ puts "created new project #{name}"
165
+ end
166
+ end
167
+
168
+ end
169
+ end
@@ -0,0 +1,40 @@
1
+ module JennCad
2
+ class DefaultProfile
3
+ attr_accessor :colors
4
+
5
+ def auto_colors
6
+ %w(
7
+ Teal
8
+ DarkOliveGreen
9
+ Aquamarine
10
+ SteelBlue
11
+ LightCoral
12
+ OrangeRed
13
+ MediumVioletRed
14
+ DarkOrchid
15
+ HotPink
16
+ )
17
+ end
18
+
19
+ def colors
20
+ @colors ||= []
21
+ if @colors.empty?
22
+ @colors = auto_colors
23
+ end
24
+ @colors
25
+ end
26
+
27
+ # called by the command line interface when receiving normal exit status
28
+ def on_success(file)
29
+ system("echo $'\033]30;#{file}: ok\007'")
30
+ puts "ok"
31
+ end
32
+
33
+ # called by the command line interface when receiving error exit status
34
+ def on_error(file)
35
+ system("echo $'\033]30;#{file}: error\007'")
36
+ puts "error"
37
+ end
38
+
39
+ end
40
+ end
@@ -0,0 +1,89 @@
1
+ module JennCad::Extras
2
+ class Din912 < Hardware
3
+ Data = {2 => {head_dia:3.8,head_length:2,thread_length:16},
4
+ 2.5=> {head_dia:4.5,head_length:2.5,thread_length:17},
5
+ 3 => {head_dia:5.5,head_length:3,thread_length:18},
6
+ 4 => {head_dia:7.0,head_length:4,thread_length:20},
7
+ 5 => {head_dia:8.5,head_length:5,thread_length:22},
8
+ 6 => {head_dia:10,head_length:6,thread_length:24},
9
+ 8 => {head_dia:13,head_length:8,thread_length:28},
10
+ 10=> {head_dia:16,head_length:10,thread_length:32},
11
+ 12=> {head_dia:18,head_length:12,thread_length:36},
12
+ 14=> {head_dia:21,head_length:14,thread_length:40},
13
+ 16=> {head_dia:24,head_length:16,thread_length:44},
14
+ 18=> {head_dia:27,head_length:18,thread_length:48},
15
+ 20=> {head_dia:30,head_length:20,thread_length:52},
16
+ 22=> {head_dia:33,head_length:22,thread_length:56},
17
+ 24=> {head_dia:36,head_length:24,thread_length:60},
18
+ 30=> {head_dia:45,head_length:30,thread_length:72},
19
+ 36=> {head_dia:54,head_length:36,thread_length:84},
20
+ }
21
+
22
+
23
+ attr_accessor :height
24
+
25
+ def initialize(size,length,args={})
26
+ super(args)
27
+ @args = args
28
+ # options for output only:
29
+ @args[:additional_length] ||= 0
30
+ @args[:additional_diameter] ||= 0.2
31
+ @args[:head_margin] ||= 0.3
32
+ @face = args[:face] || "bottom"
33
+ @flush = args[:flush] || nil
34
+
35
+ # if @args[:washer] == true
36
+ # @washer = Washer.new(size,{:material => @args[:material], :surface => @args[:surface]})
37
+ # end
38
+
39
+ @size = size
40
+ @length = length
41
+ @transformations ||= []
42
+ end
43
+
44
+ def cut
45
+ Aggregation.new("din912f#{@face}c#{@size}l#{@length}#{option_string}", bolt_912(false, @args[:additional_length], @args[:additional_diameter], @args[:head_margin])
46
+ )
47
+ end
48
+
49
+ def show
50
+ res = bolt_912(true, 0,0)
51
+ # if @washer
52
+ # res += @washer.show
53
+ # res = res.move(z:-@washer.height)
54
+ # end
55
+ # res
56
+ Aggregation.new("din912f#{@face}s#{@size}l#{@length}#{option_string}", res)
57
+ end
58
+
59
+ def bolt_912(show, additional_length=0, addtional_diameter=0, head_margin=0)
60
+
61
+ res = cylinder(d:Data[@size][:head_dia]+head_margin,h:Data[@size][:head_length]).move(z:-Data[@size][:head_length])
62
+ total_length = @length + additional_length
63
+
64
+ if show
65
+ res.color("Gainsboro")
66
+ thread_length=Data[@size][:thread_length]
67
+ if total_length.to_f <= thread_length
68
+ res+= cylinder(d:@size+addtional_diameter, h:total_length).color("DarkGray")
69
+ else
70
+ res+= cylinder(d:@size+addtional_diameter, h:total_length-thread_length)
71
+ res+= cylinder(d:@size+addtional_diameter, h:thread_length).move(z:total_length-thread_length).color("DarkGray")
72
+ end
73
+ else
74
+ res+= cylinder(d:@size+addtional_diameter, h:total_length)
75
+ end
76
+ if @flush
77
+ if @face == :top
78
+ @flush*=-1
79
+ end
80
+ res.move(z:Data[@size][:head_length] + @flush) # this needs to be fixed, need to tell it cut height to surface + margin for openscad mess
81
+ end
82
+ case @face
83
+ when :top
84
+ res = res.mirror(z:1)
85
+ end
86
+ res
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,64 @@
1
+ module JennCad::Extras
2
+ class Din933 < Hardware
3
+ attr_accessor :height
4
+
5
+ def initialize(size,length,args={})
6
+ super(args)
7
+ @args = args
8
+ # options for output only:
9
+ @args[:additional_length] ||= 0
10
+ @args[:additional_diameter] ||= 0.3
11
+ @args[:head_margin] ||= 0.0
12
+
13
+ #if @args[:washer] == true
14
+ # @washer = Washer.new(size,{:material => @args[:material], :surface => @args[:surface]})
15
+ #end
16
+
17
+ @size = size
18
+ @length = length
19
+ @transformations ||= []
20
+ end
21
+
22
+ def cut
23
+ res = bolt_933(@args[:additional_length], @args[:additional_diameter], @args[:head_margin])
24
+ Aggregation.new("din933c#{@size}#{option_string}", res)
25
+ end
26
+
27
+ def show
28
+ res = bolt_933(0,0)
29
+ #if @washer
30
+ # res += @washer.show
31
+ # res = res.move(z:-@washer.height)
32
+ #end
33
+ res.color("DarkGray")
34
+ Aggregation.new("din933s#{@size}#{option_string}", res)
35
+ end
36
+
37
+ def bolt_933(additional_length=0, addtional_diameter=0, head_margin=0)
38
+
39
+ chart = {2 => {head_side_to_side:4,head_length:1.4},
40
+ 2.5=> {head_side_to_side:5,head_length:1.7},
41
+ 3 => {head_side_to_side:5.5,head_length:2},
42
+ 4 => {head_side_to_side:7,head_length:2.8},
43
+ 5 => {head_side_to_side:8,head_length:3.5},
44
+ 6 => {head_side_to_side:10,head_length:4},
45
+ 8 => {head_side_to_side:13,head_length:5.5},
46
+ 10=> {head_side_to_side:17,head_length:7},
47
+ 12=> {head_side_to_side:19,head_length:8},
48
+ 14=> {head_side_to_side:22,head_length:9},
49
+ 16=> {head_side_to_side:24,head_length:10},
50
+ }
51
+ head_dia = chart[@size][:head_side_to_side].to_f + head_margin.to_f
52
+ res = cylinder(d:(head_dia/Math.sqrt(3))*2,fn:6,h:chart[@size][:head_length]).move(z:-chart[@size][:head_length])
53
+ total_length = @length + additional_length
54
+ res+= cylinder(d:@size+addtional_diameter, h:total_length)
55
+ end
56
+
57
+
58
+
59
+
60
+ end
61
+
62
+
63
+
64
+ end
@@ -0,0 +1,99 @@
1
+ module JennCad::Extras
2
+ class Din934 < Hardware
3
+ attr_accessor :height
4
+ attr_accessor :data
5
+ Data = {2.5=> {side_to_side:5,height:2, support_diameter:2.8},
6
+ 3 => {side_to_side:5.5,height:2.4, support_diameter:3.5},
7
+ 4 => {side_to_side:7,height:3.2, support_diameter:4.4},
8
+ 5 => {side_to_side:8,height:4, support_diameter:5.3},
9
+ 6 => {side_to_side:10,height:5, support_diameter:6.3},
10
+ 8 => {side_to_side:13,height:6.5, support_diameter:8.3},
11
+ 10 => {side_to_side:17,height:8, support_diameter:10.3},
12
+ 12 => {side_to_side:19,height:10, support_diameter:12.3},
13
+ }
14
+
15
+
16
+ def initialize(size,args={})
17
+ @size = size
18
+ @options = args.dup
19
+ @support = args[:support] ||= false
20
+ @support_layer_height = args[:support_layer_height] ||= 0.2
21
+ @margin = args[:margin] ||= 0.2 # default output margin
22
+
23
+ @slot = args[:slot] || nil
24
+ @slot_margin = args[:slot_margin] || 0.2
25
+ @slot_direction = args[:slot_direction] || "z"
26
+ @cylinder_length = args[:cylinder_length] || 0 # for slot only
27
+
28
+ @transformations ||= []
29
+ @args = args
30
+
31
+ @direction = args[:direction] || @slot_direction
32
+
33
+ @s = Data[@size][:side_to_side]
34
+ @height = Data[@size][:height]
35
+ @support_diameter = Data[@size][:support_diameter]
36
+ super(args)
37
+ end
38
+
39
+ def add_support(layer_height=@support_layer_height)
40
+ res = cylinder(d:@support_diameter,h:@height-layer_height)
41
+ # on very small nuts, add a support base of one layer height, so the support won't fall over
42
+ if @size < 6
43
+ res += cylinder(d:@s-1,h:layer_height)
44
+ end
45
+ res
46
+ end
47
+
48
+ def slot
49
+ case @slot_direction
50
+ when "x"
51
+ pos = {x:@slot}
52
+ when "y"
53
+ pos = {y:@slot}
54
+ when "z"
55
+ pos = {z:@slot}
56
+ when "-x"
57
+ pos = {x:-@slot}
58
+ when "-y"
59
+ pos = {y:-@slot}
60
+ when "-z"
61
+ pos = {z:-@slot}
62
+ else
63
+ raise "Invalid slot direction #{@slot_direction}"
64
+ end
65
+ res = hull(
66
+ nut_934(false,@margin,@slot_margin),
67
+ nut_934(false,@margin,@slot_margin).move(pos)
68
+ )
69
+ if @cylinder_length > 0
70
+ res += cylinder(d:@size+@margin,h:@cylinder_length)
71
+ end
72
+ res
73
+ end
74
+
75
+ def cut
76
+ Aggregation.new("din934c#{@size}#{option_string}", nut_934(false,@margin))
77
+ end
78
+
79
+ def show
80
+ Aggregation.new("din934s#{@size}#{option_string}", nut_934)
81
+ end
82
+
83
+ def nut_934(show=true,margin=0,height_margin=0)
84
+ size = @s + margin
85
+
86
+ res = cylinder(d:(size/Math.sqrt(3))*2,h:@height+height_margin,fn:6)
87
+ res -= cylinder(d:@size,h:@height) if show == true
88
+ if @support
89
+ res -= add_support
90
+ end
91
+ res.color("Gainsboro") if show
92
+ res
93
+ end
94
+
95
+ end
96
+
97
+
98
+
99
+ end
@@ -0,0 +1,16 @@
1
+ module JennCad::Extras
2
+ class Hardware
3
+ attr_accessor :z_fight
4
+ def initialize(args)
5
+ @options ||= {}
6
+ end
7
+
8
+ def option_string
9
+ str =""
10
+ @options.each do |k,v|
11
+ str << "#{k}#{v}"
12
+ end
13
+ str.gsub(".","_")
14
+ end
15
+ end
16
+ end