jenncad 1.0.0.pre.alpha1

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.
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