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.
- checksums.yaml +7 -0
- data/Rakefile +1 -0
- data/bin/jenncad +10 -0
- data/examples/old/cube.rb +12 -0
- data/examples/old/slot.rb +10 -0
- data/examples/old/test.rb +18 -0
- data/examples/old/test1.rb +21 -0
- data/examples/old/test2.rb +9 -0
- data/examples/old/test3.rb +15 -0
- data/examples/old/test4.rb +17 -0
- data/examples/old/test5.rb +31 -0
- data/jenncad.gemspec +27 -0
- data/lib/jenncad/commands.rb +169 -0
- data/lib/jenncad/default_profile.rb +40 -0
- data/lib/jenncad/extras/din912.rb +89 -0
- data/lib/jenncad/extras/din933.rb +64 -0
- data/lib/jenncad/extras/din934.rb +99 -0
- data/lib/jenncad/extras/hardware.rb +16 -0
- data/lib/jenncad/extras/iso7380.rb +58 -0
- data/lib/jenncad/jenncad.rb +3 -0
- data/lib/jenncad/openscad.rb +274 -0
- data/lib/jenncad/part.rb +14 -0
- data/lib/jenncad/patches/array.rb +29 -0
- data/lib/jenncad/primitives/aggregation.rb +12 -0
- data/lib/jenncad/primitives/boolean_object.rb +76 -0
- data/lib/jenncad/primitives/circle.rb +11 -0
- data/lib/jenncad/primitives/cube.rb +69 -0
- data/lib/jenncad/primitives/cylinder.rb +52 -0
- data/lib/jenncad/primitives/hull_object.rb +4 -0
- data/lib/jenncad/primitives/intersection_object.rb +4 -0
- data/lib/jenncad/primitives/linear_extrude.rb +25 -0
- data/lib/jenncad/primitives/openscad_include.rb +11 -0
- data/lib/jenncad/primitives/polygon.rb +9 -0
- data/lib/jenncad/primitives/primitive.rb +24 -0
- data/lib/jenncad/primitives/projection.rb +9 -0
- data/lib/jenncad/primitives/rotate_extrude.rb +20 -0
- data/lib/jenncad/primitives/rounded_cube.rb +77 -0
- data/lib/jenncad/primitives/slot.rb +82 -0
- data/lib/jenncad/primitives/sphere.rb +11 -0
- data/lib/jenncad/primitives/subtract_object.rb +84 -0
- data/lib/jenncad/primitives/union_object.rb +5 -0
- data/lib/jenncad/profile_loader.rb +34 -0
- data/lib/jenncad/project.rb +28 -0
- data/lib/jenncad/register.rb +31 -0
- data/lib/jenncad/shortcuts.rb +109 -0
- data/lib/jenncad/thing.rb +308 -0
- data/lib/jenncad/transformation/color.rb +8 -0
- data/lib/jenncad/transformation/mirror.rb +7 -0
- data/lib/jenncad/transformation/move.rb +7 -0
- data/lib/jenncad/transformation/multmatrix.rb +9 -0
- data/lib/jenncad/transformation/rotate.rb +7 -0
- data/lib/jenncad/transformation/scale.rb +7 -0
- data/lib/jenncad/transformation/transformation.rb +14 -0
- data/lib/jenncad/version.rb +4 -0
- data/lib/jenncad.rb +73 -0
- data/todo.txt +29 -0
- 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,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
|
data/lib/jenncad/part.rb
ADDED
@@ -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,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,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,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,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
|