jenncad 1.0.0.pre.alpha1 → 1.0.0.pre.alpha2

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.
@@ -1,274 +0,0 @@
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