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
@@ -0,0 +1,20 @@
1
+ module JennCad::Primitives
2
+ attr_accessor :convexity
3
+ class RotateExtrude < JennCad::Thing
4
+ def initialize(part, args)
5
+ @transformations = []
6
+ @parts = [part]
7
+ @angle = args[:angle]
8
+ @cut = args[:cut]
9
+ @fn = args[:fn]
10
+ end
11
+
12
+ def openscad_params
13
+ res = {}
14
+ [:cut, :angle, :convexity, :fn].each do |n|
15
+ res[n] = self.send n
16
+ end
17
+ res
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,77 @@
1
+ module JennCad::Primitives
2
+ class RoundedCube < Primitive
3
+ attr_accessor :d, :r
4
+
5
+ def initialize(args)
6
+ if args.kind_of?(Array) && args[0].kind_of?(Hash)
7
+ args = args.first
8
+ end
9
+ if args.kind_of? Array
10
+ m = {}
11
+ if args.last.kind_of? Hash
12
+ m = args.last
13
+ end
14
+ args = [:x, :y, :z, :d].zip(args.flatten).to_h.compact
15
+ args.deep_merge!(m)
16
+ end
17
+
18
+ @opts = {
19
+ d: 5,
20
+ x: 0,
21
+ y: 0,
22
+ z: nil,
23
+ r: nil,
24
+ flat_edges: nil,
25
+ margins: {
26
+ r: 0,
27
+ d: 0,
28
+ x: 0,
29
+ y: 0,
30
+ z: 0,
31
+ },
32
+ }.deep_merge!(args)
33
+ handle_margins
34
+ handle_diameter
35
+ super(opts)
36
+ end
37
+
38
+ def to_openscad
39
+ return cube(@opts) if @d == 0
40
+ # make diameter not bigger than any side
41
+ @d = [@d, @x, @y].min
42
+ res = HullObject.new(
43
+ cylinder(d:@d, h:@z).moveh(x: -@x + @d, y: @y - @d),
44
+ cylinder(d:@d).moveh(x: @x - @d, y: @y - @d),
45
+ cylinder(d:@d).moveh(x: -@x + @d, y: -@y + @d),
46
+ cylinder(d:@d).moveh(x: @x - @d, y: -@y + @d),
47
+ )
48
+
49
+ if @opts[:flat_edges]
50
+ if @opts[:flat_edges].kind_of?(Array)
51
+ @opts[:flat_edges].each do |e|
52
+ res += flat_edge(e)
53
+ end
54
+ else
55
+ res += flat_edge(@opts[:flat_edges])
56
+ end
57
+ end
58
+
59
+ res.transformations = @transformations
60
+ res
61
+ end
62
+
63
+ def flat_edge(edge)
64
+ case edge
65
+ when :up
66
+ cube(@x, @y/2.0, @z).moveh(y:@y/2.0)
67
+ when :down
68
+ cube(@x, @y/2.0, @z).moveh(y:-@y/2.0)
69
+ when :right
70
+ cube(@x/2.0, @y, @z).moveh(x:@x/2.0)
71
+ when :left
72
+ cube(@x/2.0, @y, @z).moveh(x:-@x/2.0)
73
+ end
74
+ end
75
+
76
+ end
77
+ end
@@ -0,0 +1,82 @@
1
+ module JennCad::Primitives
2
+ class Slot < Primitive
3
+ attr_accessor :d, :r, :h, :fn, :len_x, :len_y
4
+
5
+ def initialize(args)
6
+ if args.kind_of?(Array) && args[0].kind_of?(Hash)
7
+ args = args.first
8
+ end
9
+ if args.kind_of? Array
10
+ m = {}
11
+ if args.last.kind_of? Hash
12
+ m = args.last
13
+ end
14
+ args = [:d, :z].zip(args.flatten).to_h
15
+ args.deep_merge!(m)
16
+ end
17
+
18
+ args[:z] ||= args[:h]
19
+
20
+ @opts = {
21
+ d: 0,
22
+ a: 0,
23
+ z: nil,
24
+ r: nil,
25
+ x: 0,
26
+ y: 0,
27
+ margins: {
28
+ r: 0,
29
+ d: 0,
30
+ z: 0,
31
+ },
32
+ }.deep_merge!(args)
33
+
34
+ super(opts)
35
+
36
+ @d = @opts[:d]
37
+ @a = @opts[:a]
38
+ @h = @opts[:h]
39
+ @r = @opts[:r]
40
+ @fn = @opts[:fn]
41
+ @len_x = @opts[:x]
42
+ @len_y = @opts[:y]
43
+ end
44
+
45
+ def to_openscad
46
+ c1 = cylinder(@opts)
47
+ c2 = cylinder(@opts)
48
+ if @len_x
49
+ c2.move(x:@len_x)
50
+ end
51
+ if @len_y
52
+ c2.move(y:@len_y)
53
+ end
54
+ res = c1 & c2
55
+ if @a != 0.0
56
+ res = res.rotate(z:@a)
57
+ end
58
+ if @transformations && @transformations.size > 0
59
+ res = UnionObject.new([res])
60
+ res.transformations = @transformations
61
+ return res
62
+ end
63
+ res
64
+ end
65
+
66
+ def end_vector
67
+ if @a.to_f == 0.0
68
+ return [@len_x, 0] if @len_x
69
+ return [0, @len_y] if @len_y
70
+ end
71
+ if @len_x
72
+ x = cos(PI*@a/180.0)*@len_x.to_f
73
+ y = sin(PI*@a/180.0)*@len_x.to_f
74
+ else
75
+ x = -1* sin(PI*@a/180.0)*@len_y.to_f
76
+ y = cos(PI*@a/180.0)*@len_y.to_f
77
+ end
78
+ [x,y]
79
+ end
80
+
81
+ end
82
+ end
@@ -0,0 +1,11 @@
1
+ module JennCad::Primitives
2
+ class Sphere < Primitive
3
+ attr_accessor :d, :r, :fn
4
+ def initialize(args)
5
+ super
6
+ @d = args[:d]
7
+ @r = args[:r]
8
+ @fn = args[:fn]
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,84 @@
1
+ module JennCad::Primitives
2
+ class SubtractObject < BooleanObject
3
+ def inherit_z
4
+ @z = 0
5
+ @calc_z = parts.first.calc_z.to_f
6
+ only_additives_of(@parts).each do |p|
7
+ z = p.z.to_f
8
+ @z = z if z > @z
9
+ end
10
+ end
11
+
12
+ def get_heights(obj)
13
+ res = []
14
+ obj.each do |part|
15
+ if part.respond_to? :calc_h
16
+ res << part.calc_h
17
+ end
18
+ end
19
+ res
20
+ end
21
+
22
+ def get_z(obj)
23
+ res = []
24
+ obj.each do |part|
25
+ if part.respond_to? :calc_z
26
+ res << part.calc_z
27
+ end
28
+ end
29
+ res
30
+ end
31
+
32
+ def analyze_z_fighting
33
+ first = get_primitives(@parts.first).flatten
34
+ others = get_primitives(@parts[1..-1]).flatten
35
+
36
+ first_h = get_heights(first).uniq
37
+ first_z = get_z(first).uniq
38
+ #puts first.inspect
39
+ if first_h.size > 1
40
+ # puts "first item has multiple heights: #{first_h.inspect}"
41
+ first_h.each do |h|
42
+ compare_z(others, h, first_z.first)
43
+ end
44
+ else
45
+ compare_z(others, first_h.first, first_z.first)
46
+ end
47
+ end
48
+
49
+ # FIXME
50
+ # this won't work reliable with Aggregations at the moment;
51
+ # they don't have calc_z for comparing with the top
52
+ # and it will try to move the Aggregation which it should not do
53
+ # (it should move the calls to the Aggregation, not the Aggregation itself)
54
+ def compare_z(others,compare_h,compare_z)
55
+ others.each do |part|
56
+ #puts part.inspect
57
+ #puts "#{part.calc_z+part.calc_h} ; #{compare_h}"
58
+ if part.respond_to? :z
59
+ if part.referenced_z && part.z != 0.0
60
+ case part
61
+ when JennCad::BooleanObject
62
+ else
63
+ part.z+=0.2
64
+ part.translate(z:-0.1)
65
+ end
66
+ elsif part.z == compare_h
67
+ # puts "fixing possible z fighting: #{part.class} #{part.z}"
68
+ part.z+=0.008
69
+ part.translate(z:-0.004)
70
+ elsif part.calc_z == compare_z
71
+ # puts "z fighting at bottom: #{part.calc_z}"
72
+ part.z+=0.004
73
+ part.translate(z:-0.002)
74
+ elsif part.calc_z.to_f+part.calc_h.to_f == compare_h
75
+ # puts "z fighting at top: #{compare_h}"
76
+ part.z+=0.004
77
+ part.translate(z:0.002)
78
+ end
79
+ end
80
+ end
81
+ end
82
+
83
+ end
84
+ end
@@ -0,0 +1,5 @@
1
+ module JennCad::Primitives
2
+ class UnionObject < BooleanObject
3
+
4
+ end
5
+ end
@@ -0,0 +1,34 @@
1
+ module JennCad
2
+ class ProfileLoader
3
+ def initialize
4
+ load_profile
5
+ end
6
+
7
+ def profile_dir
8
+ File.expand_path(["~", ".config", "jenncad"].join("/"))
9
+ end
10
+
11
+ def profile_path
12
+ [profile_dir, "profile.rb"].join("/")
13
+ end
14
+
15
+ def load_profile
16
+ if File.exists?(profile_path)
17
+ require profile_path
18
+ check_profile
19
+ else
20
+ load_defaults
21
+ end
22
+ end
23
+
24
+ def check_profile
25
+ unless defined?($jenncad_profile)
26
+ load_defaults
27
+ end
28
+ end
29
+
30
+ def load_defaults
31
+ $jenncad_profile = JennCad::DefaultProfile.new
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,28 @@
1
+ module JennCad
2
+ class Project
3
+ def output_dir
4
+ "output"
5
+ end
6
+
7
+ def outputs
8
+ self.class.instance_methods(false) - [:config, :outputs, :output_dir]
9
+ end
10
+
11
+ def run
12
+ # load all files in subdirectories
13
+ Dir.glob("*/**/*.rb").each do |file|
14
+ require "./#{file}"
15
+ end
16
+ FileUtils.mkdir_p(output_dir)
17
+ run_exports
18
+ end
19
+
20
+ def run_exports
21
+ outputs.each do |name|
22
+ part = self.send(name)
23
+ part.openscad([output_dir,"#{name}.scad"].join("/"))
24
+ end
25
+ end
26
+
27
+ end
28
+ end
@@ -0,0 +1,31 @@
1
+ module JennCad
2
+
3
+ class Register
4
+ def initialize
5
+ @counts = {}
6
+ @objects = {}
7
+ end
8
+
9
+ def register(cl, args)
10
+ if @objects[cl] == nil || @objects[cl][args] == nil
11
+ register_new(cl, args)
12
+ end
13
+ return @objects[cl][args]
14
+ end
15
+
16
+ def register_new(cl,args)
17
+ @counts[cl] ||= {}
18
+ @objects[cl] ||= {}
19
+ if @counts[cl][args]
20
+ @counts[cl][args] += 1
21
+ else
22
+ @counts[cl][args] = 1
23
+ end
24
+
25
+ @objects[cl][args] = cl.send :new, args
26
+ end
27
+ end
28
+
29
+ $parts = Register.new
30
+
31
+ end
@@ -0,0 +1,109 @@
1
+ module JennCad
2
+ def circle(args)
3
+ Circle.new(args)
4
+ end
5
+
6
+ def cylinder(*args)
7
+ Cylinder.new(args)
8
+ end
9
+ alias :cy :cylinder
10
+ alias :cyl :cylinder
11
+
12
+ def sphere(args)
13
+ Sphere.new(args)
14
+ end
15
+ alias :sp :sphere
16
+
17
+ def polygon(args)
18
+ Polygon.new(args)
19
+ end
20
+
21
+ def slot(*args)
22
+ Slot.new(args)
23
+ end
24
+
25
+ def cube(*args)
26
+ Cube.new(args)
27
+ end
28
+ alias :cu :cube
29
+
30
+ def rounded_cube(*args)
31
+ RoundedCube.new(args)
32
+ end
33
+ alias :rcube :rounded_cube
34
+ alias :rc :rounded_cube
35
+
36
+ # import/use OpenScad library
37
+ def import(import,name,args)
38
+ OpenScadImport.new(import, name, args)
39
+ end
40
+
41
+ def extrude(args)
42
+ LinearExtrude.new(self, args)
43
+ end
44
+
45
+ def rotate_extrude(args={})
46
+ RotateExtrude.new(self, args)
47
+ end
48
+
49
+ def to_2d(args={})
50
+ Projection.new(self, args)
51
+ end
52
+
53
+ def union(*args)
54
+ UnionObject.new(*args)
55
+ end
56
+
57
+ def +(args)
58
+ return args if self == nil
59
+ if self.kind_of?(UnionObject) && self.transformations.size == 0
60
+ self.add(args)
61
+ return self
62
+ else
63
+ UnionObject.new(self,args)
64
+ end
65
+ end
66
+
67
+ def subtraction(*args)
68
+ SubtractObject.new(*args)
69
+ end
70
+
71
+ def -(args)
72
+ if self.kind_of?(SubtractObject) && self.transformations.size == 0
73
+ self.add(args)
74
+ return self
75
+ else
76
+ SubtractObject.new(self,args)
77
+ end
78
+ end
79
+
80
+ def intersection(*args)
81
+ IntersectionObject.new(*args)
82
+ end
83
+
84
+ def *(args)
85
+ if self.kind_of?(IntersectionObject) && self.transformations.size == 0
86
+ self.add(args)
87
+ return self
88
+ else
89
+ IntersectionObject.new(self,args)
90
+ end
91
+ end
92
+
93
+ def hull(*args)
94
+ HullObject.new(*args)
95
+ end
96
+
97
+ def &(args)
98
+ if self.kind_of?(HullObject) && self.transformations.size == 0
99
+ self.add(args)
100
+ return self
101
+ else
102
+ HullObject.new(self,args)
103
+ end
104
+ end
105
+
106
+ def assemble(partlib=nil, z_skip = false, z=0, &block)
107
+ block.yield.assemble(partlib, z_skip, z)
108
+ end
109
+ end