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,58 @@
1
+ module JennCad::Extras
2
+ class Iso7380 < 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_7380(@args[:additional_length], @args[:additional_diameter], @args[:head_margin])
24
+ Aggregation.new("iso7380c#{@size}#{option_string}", res)
25
+ end
26
+
27
+ def show
28
+ res = bolt_7380(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("iso7380s#{@size}#{option_string}", res)
35
+ end
36
+
37
+ # ISO 7380
38
+ def bolt_7380(additional_length=0, addtional_diameter=0, head_margin=0)
39
+ if head_margin.to_f != 0
40
+ puts "[warning] :head_margin is not implemented for 7380 bolts"
41
+ end
42
+ chart_iso7380 = {
43
+ 3 => {head_dia:5.7,head_length:1.65},
44
+ 4 => {head_dia:7.6,head_length:2.2},
45
+ 5 => {head_dia:9.5,head_length:2.75},
46
+ 6 => {head_dia:10.5,head_length:3.3},
47
+ 8 => {head_dia:14,head_length:4.4},
48
+ 10=> {head_dia:17.5,head_length:5.5},
49
+ 12=> {head_dia:21,head_length:6.6},
50
+
51
+
52
+ }
53
+ res = cylinder(d1:chart_iso7380[@size][:head_dia]/2.0,d2:chart_iso7380[@size][:head_dia],h:chart_iso7380[@size][:head_length]).move(z:-chart_iso7380[@size][:head_length])
54
+ total_length = @length + additional_length
55
+ res+= cylinder(d:@size+addtional_diameter, h:total_length)
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,3 @@
1
+ module JennCad
2
+ include Primitives
3
+ end
@@ -0,0 +1,274 @@
1
+ module JennCad
2
+
3
+ class OpenScad
4
+ def initialize(part, fn=64)
5
+ @imports = []
6
+ @modules = {}
7
+ part = part.make_openscad_compatible
8
+ @main = root(part, "$fn=#{fn};\n")
9
+
10
+ @export = ""
11
+ @imports.uniq.each do |val|
12
+ @export += "use <#{val}.scad>\n"
13
+ end
14
+ @modules.each do |key, val|
15
+ @export += val
16
+ end
17
+ @export += @main
18
+ end
19
+
20
+ def save(file)
21
+ File.open(file,"w") do |f|
22
+ f.puts @export
23
+ end
24
+ end
25
+
26
+ def root(part, head="", tabindex=0)
27
+ res = head
28
+
29
+ res += transform(part) do
30
+ parse(part, tabindex)
31
+ end
32
+ res
33
+ end
34
+
35
+ def transform(part, &block)
36
+ res += handle_color(part)
37
+ if part.transformations
38
+ part.transformations.reverse.each do |trans|
39
+ res += transformation(trans)
40
+ end
41
+ end
42
+ res += block.yield
43
+ end
44
+
45
+ def print_tree(part, level=0)
46
+ arr = []
47
+ arr << parse(part) unless level == 0
48
+ if part.respond_to?(:parts)
49
+ part.parts.each do |p|
50
+ arr << print_tree(p,level+1)
51
+ end
52
+ end
53
+ arr
54
+ end
55
+
56
+
57
+ def parse(part, tabindex=0)
58
+ case part
59
+ when JennCad::OpenScadImport
60
+ handle_import(part)
61
+ when JennCad::Aggregation
62
+ handle_aggregation(part)
63
+ when JennCad::UnionObject
64
+ cmd('union', nil, part.parts, tabindex)
65
+ when JennCad::SubtractObject
66
+ part.analyze_z_fighting
67
+ cmd('difference', nil, part.parts, tabindex)
68
+ when JennCad::IntersectionObject
69
+ cmd('intersection', nil, part.parts, tabindex)
70
+ when JennCad::HullObject
71
+ cmd('hull', nil, part.parts, tabindex)
72
+ when JennCad::Primitives::Circle
73
+ cmd('circle', collect_params(part), nil, tabindex)
74
+ when JennCad::Primitives::Cylinder
75
+ cmd('cylinder', collect_params(part), nil, tabindex)
76
+ when JennCad::Primitives::Sphere
77
+ cmd('sphere', collect_params(part), nil, tabindex)
78
+ when JennCad::Primitives::Cube
79
+ handle_cube(part, tabindex)
80
+ when JennCad::Primitives::LinearExtrude
81
+ cmd('linear_extrude', part.openscad_params, part.parts, tabindex)
82
+ when JennCad::Primitives::RotateExtrude
83
+ cmd('rotate_extrude', part.openscad_params, part.parts, tabindex)
84
+ when JennCad::Primitives::Projection
85
+ cmd('projection', collect_params(part), part.parts, tabindex)
86
+ when JennCad::Primitives::Polygon
87
+ cmd('polygon', collect_params(part), nil, tabindex)
88
+ else
89
+ if part.respond_to?(:parts) && part.parts != nil && !part.parts.empty?
90
+ res = ""
91
+ part.parts.each do |p|
92
+ res += root(p, "", tabindex)
93
+ end
94
+ return res
95
+ elsif part.respond_to?(:part)
96
+ return root(part.part, "", tabindex)
97
+ end
98
+ puts "no idea what to do with #{part.inspect}"
99
+ return ""
100
+ end
101
+ end
102
+
103
+ def fmt_params(args)
104
+ return "" if args == nil
105
+ if args.kind_of? String
106
+ return "\"#{args}\""
107
+ elsif args.kind_of? Array
108
+ return args.map do |l|
109
+ if l == nil
110
+ 0
111
+ elsif l.kind_of? Array
112
+ l # skipping check of 2-dmin Arrays for now (used in multmatrix)
113
+ elsif l.to_i == l.to_f
114
+ l.to_i
115
+ else
116
+ l.to_f
117
+ end
118
+ end
119
+ else
120
+ res = []
121
+ args.each do |k,v|
122
+ if k.to_s == "fn"
123
+ k = "$fn"
124
+ end
125
+ if v == nil
126
+ next
127
+ end
128
+ if !v.kind_of?(Array) && !v.kind_of?(TrueClass) && !v.kind_of?(FalseClass) && v == v.to_i
129
+ v = v.to_i
130
+ end
131
+ res << "#{k}=#{v}"
132
+ end
133
+ res.join(",")
134
+ end
135
+ end
136
+
137
+ def cmd(name, args, items, tabindex = 0)
138
+ items ||= []
139
+ res = cmd_call(name,args)
140
+ if items.size > 1
141
+ res << "\n"
142
+ res << tabs(tabindex) { "{\n" }
143
+ items.each do |item|
144
+ res << tabs(tabindex+1) do
145
+ transform(item) do
146
+ parse(item, tabindex+1)
147
+ end
148
+ end
149
+ end
150
+ res << tabs(tabindex) { "}\n" }
151
+ elsif items.size == 1
152
+ item = items.first
153
+ res << transform(item) do
154
+ parse(item, tabindex)
155
+ end
156
+ res << ";\n"
157
+ else
158
+ res << ";\n"
159
+ end
160
+ return res
161
+ end
162
+
163
+ def tabs(i, &block)
164
+ " " * i + block.yield
165
+ end
166
+
167
+ def handle_import(part, tabindex=0)
168
+ @imports << part.import
169
+ return tabs(tabindex){ "#{part.name}(#{fmt_params(part.args)});\n" }
170
+ end
171
+
172
+ def handle_aggregation(part, tabindex=0)
173
+ register_module(part) unless @modules[part.name]
174
+ use_module(part.name, tabindex)
175
+ end
176
+
177
+ # check children for color values
178
+ # if none of the children has a color value, we can apply color to this object and all children
179
+ # if any of the children (excluding children of the kind of BooleanObject) has a color value (that is different from ours), we will apply a fallback color to all children that do not have a color value themselves.
180
+
181
+ def handle_color(part)
182
+ if part && part.respond_to?(:color) && part.color
183
+ if part.respond_to?(:parts)
184
+ if part.children_list(JennCad::Aggregation).map{|l| l.color != nil && l.color != part.color}.include?(true)
185
+ part.children_list(JennCad::Aggregation).each do |child|
186
+ if child.color == nil && child.color != part.color && !child.kind_of?(BooleanObject)
187
+ child.set_option :fallback_color, part.color
188
+ end
189
+ end
190
+ return ""
191
+ end
192
+ end
193
+ end
194
+ return apply_color(part)
195
+ end
196
+
197
+ def apply_color(part)
198
+ if part && part.respond_to?(:color_or_fallback)
199
+ color = part.color_or_fallback
200
+ return "" if color == nil
201
+ # Allowing color to be string, OpenScad compatible RGBA values of 0..1 or RGBA values of 0..255
202
+ if color.kind_of?(Array) && color.map{|l| l.to_f > 1.0 ? true : false}.include?(true)
203
+ color = color.map{|l| l.to_f/255.0}
204
+ end
205
+ return cmd_call("color", color)
206
+ end
207
+ return ""
208
+ end
209
+
210
+ def register_module(part)
211
+ # can only accept aggregation
212
+ @modules[part.name] = "module #{part.name}(){\n"
213
+ @modules[part.name] += root(part.part)
214
+ @modules[part.name] += "}\n"
215
+ end
216
+
217
+ def use_module(name, tabindex)
218
+ tabs(tabindex){ cmd_call(name, nil).to_s+";" }
219
+ end
220
+
221
+ def cmd_call(name, args)
222
+ args = fmt_params(args)
223
+ return "#{name}(#{args})"
224
+ end
225
+
226
+ def collect_params(part)
227
+ res = {}
228
+ [:d, :r, :h, :r1, :r2, :d1, :d2, :size, :fn, :points].each do |var|
229
+ if part.respond_to? var
230
+ res[var] = part.send var
231
+ end
232
+ end
233
+ res
234
+ end
235
+
236
+ def transformation(trans)
237
+ case trans
238
+ when JennCad::Move
239
+ cmd_call("translate",trans.coordinates)
240
+ when JennCad::Rotate
241
+ cmd_call("rotate",trans.coordinates)
242
+ when JennCad::Mirror
243
+ cmd_call("mirror",trans.coordinates)
244
+ when JennCad::Multmatrix
245
+ cmd_call("multmatrix",trans.m)
246
+ else
247
+ puts "[openscad exporter] Unkown transformation #{trans.class}"
248
+ ""
249
+ end
250
+ end
251
+
252
+ # cubes are now centered in xy by default in jenncad
253
+ # TODO: should this not be to_openscad in Cube?
254
+ def handle_cube(part, tabindex)
255
+ res = ""
256
+ if part.option(:center)
257
+ res += transformation(Move.new(x: -part.x/2.0, y: -part.y/2.0))
258
+ else
259
+ if part.option(:center_x)
260
+ res += transformation(Move.new(x: -part.x/2.0))
261
+ end
262
+ if part.option(:center_y)
263
+ res += transformation(Move.new(y: -part.y/2.0))
264
+ end
265
+ if part.option(:center_z)
266
+ res += transformation(Move.new(z: -part.z/2.0))
267
+ end
268
+ end
269
+
270
+ res += cmd('cube', collect_params(part), nil)
271
+ end
272
+
273
+ end
274
+ end
@@ -0,0 +1,14 @@
1
+ module JennCad
2
+ # Part should be inherited from the user when making parts
3
+ class Part < Thing
4
+
5
+ def make_openscad_compatible
6
+ auto_color
7
+ a = Aggregation.new(self.class.to_s, make_openscad_compatible!(self.part))
8
+ a.transformations = @transformations
9
+ a.color(color)
10
+ a
11
+ end
12
+
13
+ end
14
+ end
@@ -0,0 +1,29 @@
1
+ class Array
2
+ # Assembles things on top of each other
3
+ def assemble(partlib=nil, skip_z=false, z=0)
4
+ map do |part|
5
+ case part
6
+ when Array
7
+ res = part.assemble(partlib, true)
8
+ when String, Symbol
9
+ res = partlib[part].yield
10
+ when Proc
11
+ res = part.yield
12
+ else
13
+ res = part
14
+ end
15
+ # FIXME: I added 0.01 to all for now to fix z-fighting issues; this should not be hardcoded like this
16
+ res, z = res.move(z:z), z + res.z.to_f + 0.01 unless skip_z
17
+ res
18
+ end
19
+ .union
20
+ end
21
+
22
+ def union(&block)
23
+ if block
24
+ UnionObject.new(block.yield)
25
+ else
26
+ UnionObject.new(self)
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,12 @@
1
+ module JennCad::Primitives
2
+ class Aggregation < Primitive
3
+ attr_accessor :part
4
+
5
+ def initialize(name=nil, part=nil)
6
+ super({})
7
+ @name = name
8
+ @part = part
9
+ end
10
+
11
+ end
12
+ end
@@ -0,0 +1,76 @@
1
+ module JennCad::Primitives
2
+ class BooleanObject < Primitive
3
+ def initialize(*parts)
4
+ @transformations = []
5
+ if parts.first.kind_of? Array
6
+ @parts = parts.first
7
+ else
8
+ @parts = parts
9
+ end
10
+ after_add
11
+ end
12
+
13
+ def add(part)
14
+ @parts << part
15
+ after_add
16
+ end
17
+
18
+ def after_add
19
+ @parts.flatten!
20
+ @parts.compact!
21
+ inherit_z
22
+ inherit_zref
23
+ end
24
+
25
+ def inherit_z
26
+ heights = @parts.map{|l| l.calc_z.to_f}.uniq
27
+ if heights.size > 1
28
+ total_heights = []
29
+ @parts.each do |p|
30
+ total_heights << p.z.to_f + p.calc_z.to_f
31
+ end
32
+ @z = total_heights.max
33
+ @calc_z = heights.min
34
+ else
35
+ @calc_z = heights.first.to_f
36
+ @z = @parts.map(&:z).compact.max
37
+ end
38
+ end
39
+
40
+ def inherit_zref
41
+ return if @parts.first == nil
42
+ return if @parts.first.z.to_f == 0.0
43
+ get_primitives(@parts[1..-1]).flatten.each do |part|
44
+ if part.z.to_f == 0.0
45
+ part.set_option :zref, @parts.first
46
+ end
47
+ end
48
+ end
49
+
50
+ def get_primitives(obj)
51
+ res = []
52
+ if obj.kind_of? Array
53
+ obj.each do |part|
54
+ res << part.children_list
55
+ end
56
+ else
57
+ res << obj.children_list
58
+ end
59
+ res
60
+ end
61
+
62
+ def only_additives_of(obj)
63
+ res = []
64
+ case obj
65
+ when Array
66
+ res << obj.map{|l| only_additives_of(l)}
67
+ when SubtractObject
68
+ when IntersectionObject
69
+ else
70
+ res << obj
71
+ end
72
+ res.flatten
73
+ end
74
+
75
+ end
76
+ end
@@ -0,0 +1,11 @@
1
+ module JennCad::Primitives
2
+ class Circle < 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,69 @@
1
+ module JennCad::Primitives
2
+ class Cube < Primitive
3
+ attr_accessor :x,:y,:z
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].zip(args.flatten).to_h
15
+ args.deep_merge!(m)
16
+ end
17
+ @opts = {
18
+ x: 0,
19
+ y: 0,
20
+ z: 0,
21
+ margins: {
22
+ x: 0,
23
+ y: 0,
24
+ z: 0,
25
+ },
26
+ center: true,
27
+ center_y: false,
28
+ center_x: false,
29
+ center_z: false,
30
+ }.deep_merge!(args)
31
+ handle_margins
32
+
33
+ super(args)
34
+ @h = @z.dup
35
+ @calc_h = @z.dup
36
+ end
37
+
38
+ # used for openscad export
39
+ def size
40
+ [@x, @y, @z]
41
+ end
42
+
43
+ def center_xy
44
+ set_option :center, true
45
+ self
46
+ end
47
+
48
+ def center_x
49
+ set_option :center_x, true
50
+ self
51
+ end
52
+
53
+ def center_y
54
+ set_option :center_y, true
55
+ self
56
+ end
57
+
58
+ def center_z
59
+ set_option :center_z, true
60
+ self
61
+ end
62
+
63
+ # def center
64
+ # @transformations << Move.new({x:-@x/2,y:-@y/2,z:-@z/2})
65
+ # self
66
+ # end
67
+
68
+ end
69
+ end
@@ -0,0 +1,52 @@
1
+ module JennCad::Primitives
2
+ class Cylinder < Primitive
3
+ attr_accessor :d, :r, :fn
4
+ def initialize(args)
5
+ if args.kind_of?(Array) && args[0].kind_of?(Hash)
6
+ args = args.first
7
+ end
8
+ if args.kind_of? Array
9
+ m = {}
10
+ if args.last.kind_of? Hash
11
+ m = args.last
12
+ end
13
+ args = [:d, :z].zip(args.flatten).to_h
14
+ args.deep_merge!(m)
15
+ end
16
+
17
+ args[:z] ||= args[:h]
18
+
19
+ @opts = {
20
+ d: 0,
21
+ z: nil,
22
+ r: 0,
23
+ margins: {
24
+ r: 0,
25
+ d: 0,
26
+ z: 0,
27
+ },
28
+ fn: nil,
29
+ }.deep_merge!(args)
30
+
31
+ # FIXME:
32
+ # - margins calculation needs to go to output
33
+ # - assinging these variables has to stop
34
+ # - r/d need to be automatically calculated by each other
35
+ # - r+z margin not implemented atm
36
+ # - need to migrate classes to provide all possible outputs (and non-conflicting ones) to openscad exporter
37
+ @d = args[:d] + @opts[:margins][:d]
38
+ @z = args[:z] || args[:h]
39
+ @r = args[:r]
40
+ @fn = args[:fn]
41
+ if @fn == nil && @d > 16
42
+ @fn = (@d*4).ceil
43
+ end
44
+ super(args)
45
+ end
46
+
47
+ def h
48
+ z
49
+ end
50
+
51
+ end
52
+ end
@@ -0,0 +1,4 @@
1
+ module JennCad::Primitives
2
+ class HullObject < BooleanObject
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module JennCad::Primitives
2
+ class IntersectionObject < BooleanObject
3
+ end
4
+ end
@@ -0,0 +1,25 @@
1
+ module JennCad::Primitives
2
+ attr_accessor :center_bool, :convexity, :twist, :slices, :height
3
+ class LinearExtrude < JennCad::Thing
4
+ def initialize(part, args)
5
+ @transformations = []
6
+ @parts = [part]
7
+ @height = args[:h] || args[:height]
8
+ @center_bool = args[:center]
9
+ @convexity = args[:convexity]
10
+ @twist = args[:twist]
11
+ @slices = args[:slices]
12
+ @fn = args[:fn]
13
+ end
14
+
15
+ def openscad_params
16
+ res = {}
17
+ [:height, :convexity, :twist, :slices, :fn].each do |n|
18
+ res[n] = self.send n
19
+ end
20
+ res[:center] = @center_bool
21
+ res
22
+ end
23
+ end
24
+
25
+ end
@@ -0,0 +1,11 @@
1
+ module JennCad::Primitives
2
+ class OpenScadImport < Aggregation
3
+ attr_accessor :import, :args
4
+
5
+ def initialize(import, name, args)
6
+ @import = import
7
+ @name = name
8
+ @args = args
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,9 @@
1
+ module JennCad::Primitives
2
+ class Polygon < Primitive
3
+ attr_accessor :points
4
+ def initialize(args)
5
+ super
6
+ @points = args[:points]
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,24 @@
1
+ module JennCad::Primitives
2
+ class Primitive < JennCad::Thing
3
+ def initialize(*args)
4
+ super(*args)
5
+ end
6
+
7
+ def handle_margins
8
+ @x = @opts[:x] + @opts[:margins][:x]
9
+ @y = @opts[:y] + @opts[:margins][:y]
10
+ @z = @opts[:z] + @opts[:margins][:z]
11
+ end
12
+
13
+ def handle_diameter
14
+ @d = opts[:d]
15
+ @r = opts[:r]
16
+ if @d
17
+ @r = @d/2.0
18
+ elsif @r
19
+ @d = @r*2
20
+ end
21
+ end
22
+
23
+ end
24
+ end
@@ -0,0 +1,9 @@
1
+ module JennCad::Primitives
2
+ class Projection < JennCad::Thing
3
+ def initialize(part, args)
4
+ @transformations = []
5
+ @cut = args[:cut]
6
+ @parts = [part]
7
+ end
8
+ end
9
+ end