jenncad 1.0.0.pre.alpha12 → 1.0.0.pre.alpha15
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/jenncad/default_profile.rb +12 -0
- data/lib/jenncad/exporters/openscad.rb +18 -11
- data/lib/jenncad/extras/din912.rb +1 -1
- data/lib/jenncad/extras/din933.rb +1 -1
- data/lib/jenncad/extras/iso7380.rb +1 -1
- data/lib/jenncad/features/aggregation.rb +1 -1
- data/lib/jenncad/features/climb.rb +5 -3
- data/lib/jenncad/features/cuttable.rb +2 -2
- data/lib/jenncad/features/multiples_of.rb +14 -0
- data/lib/jenncad/features/path.rb +27 -20
- data/lib/jenncad/features.rb +2 -0
- data/lib/jenncad/part.rb +6 -2
- data/lib/jenncad/patches/array.rb +1 -1
- data/lib/jenncad/primitives/boolean_object.rb +13 -5
- data/lib/jenncad/primitives/cube.rb +7 -0
- data/lib/jenncad/primitives/cylinder.rb +41 -9
- data/lib/jenncad/primitives/primitive.rb +5 -5
- data/lib/jenncad/primitives/slot.rb +21 -6
- data/lib/jenncad/primitives/subtract_object.rb +3 -3
- data/lib/jenncad/shortcuts.rb +11 -1
- data/lib/jenncad/thing.rb +124 -52
- data/lib/jenncad/transformation/color.rb +1 -1
- data/lib/jenncad/version.rb +1 -2
- data/lib/jenncad.rb +1 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3eebd115b8e6783b61fff33f1b002f935f3d2c2023df70df9ff3b9850f12245f
|
4
|
+
data.tar.gz: 806a99e1195f98ee1e8450030f9e2809c11217af7bf19e8cac88ad9408146a40
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a120ac12bfe18f3532560c10452ae9460d21bd8ba2e4d287669b9b23cdf903476541fed341b81ce7feb8e906ccc8087a7a0f46f5f49e63d66b6421cd8e4d0984
|
7
|
+
data.tar.gz: 06e239cea5a153ecb3b8ab1873574bc8d9a03e51d1c0d75e5fe72f393e1584971bbc2ba388d9da82ce58cc79c2f949e206962be9052da29b0a24e351c176a53d
|
@@ -16,6 +16,18 @@ module JennCad
|
|
16
16
|
)
|
17
17
|
end
|
18
18
|
|
19
|
+
# By default, jenncad will add coordinates of subsequent moves in the output
|
20
|
+
# i.e.
|
21
|
+
# .move(x: 10, y: 20).move(x: 10) would result depending on the value of this option:
|
22
|
+
#
|
23
|
+
# true = translate([10,20, 0])translate([10, 0, 0])
|
24
|
+
# false = translate([20, 20, 0])
|
25
|
+
#
|
26
|
+
# defaults to false
|
27
|
+
def chain_moves
|
28
|
+
false
|
29
|
+
end
|
30
|
+
|
19
31
|
def colors
|
20
32
|
case @colors
|
21
33
|
when nil, []
|
@@ -45,11 +45,11 @@ module JennCad::Exporters
|
|
45
45
|
def handle_command(i=1)
|
46
46
|
case @children.size
|
47
47
|
when 0
|
48
|
-
"#{@modifier}#{@command}(#{handle_args});"
|
48
|
+
"#{@modifier}#{@command}(#{handle_args(@args)});"
|
49
49
|
when 1
|
50
|
-
"#{@modifier}#{@command}(#{handle_args})#{@children.first.handle_command(i+1)}"
|
50
|
+
"#{@modifier}#{@command}(#{handle_args(@args)})#{@children.first.handle_command(i+1)}"
|
51
51
|
when (1..)
|
52
|
-
res = "#{@modifier}#{@command}(#{handle_args}){"
|
52
|
+
res = "#{@modifier}#{@command}(#{handle_args(@args)}){"
|
53
53
|
res += nl
|
54
54
|
inner = @children.map do |c|
|
55
55
|
next if c == nil
|
@@ -68,17 +68,19 @@ module JennCad::Exporters
|
|
68
68
|
}.join(nl)
|
69
69
|
end
|
70
70
|
|
71
|
-
def handle_args
|
72
|
-
case
|
71
|
+
def handle_args(args)
|
72
|
+
case args
|
73
73
|
when String, Symbol
|
74
|
-
return "\"#{
|
74
|
+
return "\"#{args}\""
|
75
75
|
when Array
|
76
|
-
return
|
76
|
+
return args.map do |l|
|
77
77
|
if l == nil
|
78
78
|
0
|
79
79
|
elsif l.kind_of? Array
|
80
80
|
l # skipping check of 2-dmin Arrays for now (used in multmatrix)
|
81
|
-
elsif l
|
81
|
+
elsif l == 0
|
82
|
+
0
|
83
|
+
elsif l == l.to_i
|
82
84
|
l.to_i
|
83
85
|
else
|
84
86
|
l.to_f
|
@@ -86,15 +88,19 @@ module JennCad::Exporters
|
|
86
88
|
end
|
87
89
|
when Hash
|
88
90
|
res = []
|
89
|
-
|
91
|
+
args.each do |k,v|
|
90
92
|
if k.to_s == "fn"
|
91
93
|
k = "$fn"
|
92
94
|
end
|
93
95
|
if v == nil
|
94
96
|
next
|
95
97
|
end
|
96
|
-
if
|
98
|
+
if v.kind_of?(Array)
|
99
|
+
v = handle_args(v)
|
100
|
+
elsif !v.kind_of?(TrueClass) && !v.kind_of?(FalseClass) && v == v.to_i
|
97
101
|
v = v.to_i
|
102
|
+
elsif v.kind_of? BigDecimal
|
103
|
+
v = v.to_f
|
98
104
|
end
|
99
105
|
if v.kind_of? String
|
100
106
|
q = "\""
|
@@ -245,7 +251,8 @@ module JennCad::Exporters
|
|
245
251
|
|
246
252
|
def handle_aggregation(part, tabindex=0)
|
247
253
|
register_module(part) unless @modules[part.name]
|
248
|
-
|
254
|
+
$log.debug "aggregation #{part.name} transformations: #{part.transformations.inspect}" if part && part.option(:debug)
|
255
|
+
transform(part.clone) do
|
249
256
|
new_obj(part, part.name, nil)
|
250
257
|
end
|
251
258
|
end
|
@@ -64,7 +64,7 @@ module JennCad::Extras
|
|
64
64
|
if show
|
65
65
|
res.color("Gainsboro")
|
66
66
|
thread_length=Data[@size][:thread_length]
|
67
|
-
if total_length.
|
67
|
+
if total_length.to_d <= thread_length
|
68
68
|
res+= cylinder(d:@size+addtional_diameter, h:total_length).color("DarkGray")
|
69
69
|
else
|
70
70
|
res+= cylinder(d:@size+addtional_diameter, h:total_length-thread_length)
|
@@ -48,7 +48,7 @@ module JennCad::Extras
|
|
48
48
|
14=> {head_side_to_side:22,head_length:9},
|
49
49
|
16=> {head_side_to_side:24,head_length:10},
|
50
50
|
}
|
51
|
-
head_dia = chart[@size][:head_side_to_side].
|
51
|
+
head_dia = chart[@size][:head_side_to_side].to_d + head_margin.to_d
|
52
52
|
res = cylinder(d:(head_dia/Math.sqrt(3))*2,fn:6,h:chart[@size][:head_length]).move(z:-chart[@size][:head_length])
|
53
53
|
total_length = @length + additional_length
|
54
54
|
res+= cylinder(d:@size+addtional_diameter, h:total_length)
|
@@ -36,7 +36,7 @@ module JennCad::Extras
|
|
36
36
|
|
37
37
|
# ISO 7380
|
38
38
|
def bolt_7380(additional_length=0, addtional_diameter=0, head_margin=0)
|
39
|
-
if head_margin.
|
39
|
+
if head_margin.to_d != 0
|
40
40
|
puts "[warning] :head_margin is not implemented for 7380 bolts"
|
41
41
|
end
|
42
42
|
chart_iso7380 = {
|
@@ -1,6 +1,8 @@
|
|
1
1
|
module JennCad::Features
|
2
2
|
class Climb < Feature
|
3
3
|
def initialize(opts, block)
|
4
|
+
$log.warn "DEPRECATED feature: climb. Please use x.of (multiples_of example)"
|
5
|
+
|
4
6
|
@opts = {
|
5
7
|
offset: :auto,
|
6
8
|
step: nil,
|
@@ -31,7 +33,7 @@ module JennCad::Features
|
|
31
33
|
steps = @opts[:steps]
|
32
34
|
(z / steps).floor
|
33
35
|
else
|
34
|
-
step.
|
36
|
+
step.to_d
|
35
37
|
end
|
36
38
|
end
|
37
39
|
|
@@ -62,8 +64,8 @@ module JennCad::Features
|
|
62
64
|
|
63
65
|
offset = get_offset(ref_z)
|
64
66
|
|
65
|
-
lo = (ref_z-offset*2).
|
66
|
-
unless lo.
|
67
|
+
lo = (ref_z-offset*2).to_d % step.to_d
|
68
|
+
unless lo.to_d == 0.0
|
67
69
|
puts "[Warning]: climb has leftover offset #{lo}"
|
68
70
|
end
|
69
71
|
|
@@ -16,12 +16,12 @@ module JennCad::Features
|
|
16
16
|
|
17
17
|
def prepare_cut(l, r, &block)
|
18
18
|
part = block.call
|
19
|
-
if part.z.
|
19
|
+
if part.z.to_d > 0.0
|
20
20
|
part.opts[:margins][:z] = 0.2
|
21
21
|
if l == 0.0
|
22
22
|
part.mz(r+0.1)
|
23
23
|
else
|
24
|
-
part.mz(l+part.z.
|
24
|
+
part.mz(l+part.z.to_d-0.2)
|
25
25
|
end
|
26
26
|
else
|
27
27
|
part.opts[:margins][:z] = 0.2
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module JennCad
|
2
2
|
class RoundCorner
|
3
3
|
attr_accessor :start_point, :end_point, :input_a, :output_a, :a, :l, :od, :id, :thing, :angle, :current_angle, :direction, :from, :ccw
|
4
|
-
def initialize(args
|
4
|
+
def initialize(args)
|
5
5
|
@start_point = args[:start_point]
|
6
6
|
@end_point = args[:end_point]
|
7
7
|
@a = args[:a]
|
@@ -11,7 +11,13 @@ module JennCad
|
|
11
11
|
@id = args[:id]
|
12
12
|
@input_a = args[:input_a] || 0
|
13
13
|
@output_a = args[:output_a] || 0
|
14
|
-
|
14
|
+
thing = Marshal.load(args[:thing])
|
15
|
+
|
16
|
+
@thing_dia = thing.d || thing.y
|
17
|
+
unless @thing_dia
|
18
|
+
$log.error "ERROR: cannot find diameter or y of thing #{thing.inspect}"
|
19
|
+
return
|
20
|
+
end
|
15
21
|
@angle = args[:angle]
|
16
22
|
@current_angle = args[:current_angle]
|
17
23
|
@direction = args[:direction]
|
@@ -57,11 +63,7 @@ module JennCad
|
|
57
63
|
end
|
58
64
|
|
59
65
|
def positions
|
60
|
-
td =
|
61
|
-
unless td
|
62
|
-
puts "ERROR: cannot find diameter or y of thing #{thing.yield.inspect}"
|
63
|
-
return
|
64
|
-
end
|
66
|
+
td = @thing_dia
|
65
67
|
l = td + @id
|
66
68
|
l2 = td / 2.0 + @id / 2.0
|
67
69
|
r = 0
|
@@ -101,7 +103,7 @@ module JennCad
|
|
101
103
|
end
|
102
104
|
|
103
105
|
def part
|
104
|
-
d =
|
106
|
+
d = @thing_dia
|
105
107
|
len = d * 2 + @id
|
106
108
|
x = Math::sin((@a/180.0)*Math::PI)*len
|
107
109
|
y = Math::cos((@a/180.0)*Math::PI)*len
|
@@ -134,15 +136,15 @@ module JennCad
|
|
134
136
|
end
|
135
137
|
|
136
138
|
class Line
|
137
|
-
attr_accessor :start_point, :end_point, :l, :
|
138
|
-
def initialize(args
|
139
|
+
attr_accessor :start_point, :end_point, :l, :angle, :current_angle, :direction
|
140
|
+
def initialize(args)
|
139
141
|
@start_point = args[:start_point]
|
140
142
|
@end_point = args[:end_point]
|
141
143
|
@angle = args[:angle]
|
142
144
|
@current_angle = args[:current_angle]
|
143
145
|
@direction = args[:direction]
|
144
146
|
@l = args[:l]
|
145
|
-
@thing = thing
|
147
|
+
@thing = args[:thing]
|
146
148
|
end
|
147
149
|
|
148
150
|
def sp_margin(margin)
|
@@ -181,8 +183,8 @@ module JennCad
|
|
181
183
|
|
182
184
|
def part
|
183
185
|
hull(
|
184
|
-
@thing.
|
185
|
-
@thing.
|
186
|
+
Marshal.load(@thing).move(x: @start_point[:x], y: @start_point[:y]),
|
187
|
+
Marshal.load(@thing).move(x: @end_point[:x], y: @end_point[:y])
|
186
188
|
)
|
187
189
|
end
|
188
190
|
end
|
@@ -191,7 +193,7 @@ module JennCad
|
|
191
193
|
|
192
194
|
attr_accessor :elements, :lpos, :thing, :angle, :current_angle, :direction
|
193
195
|
def initialize(args)
|
194
|
-
@thing = args[:part]
|
196
|
+
@thing = store_thing_from(args[:part])
|
195
197
|
@part = new_thing
|
196
198
|
@angle = args[:a] || 0
|
197
199
|
@current_angle = args[:a] || 0
|
@@ -207,10 +209,14 @@ module JennCad
|
|
207
209
|
super(args)
|
208
210
|
end
|
209
211
|
|
210
|
-
def
|
211
|
-
r =
|
212
|
+
def store_thing_from(thing)
|
213
|
+
r = Marshal.load(Marshal.dump(thing)) # make sure we don't edit the object in memory
|
212
214
|
r.transformations = []
|
213
|
-
r
|
215
|
+
Marshal.dump(r)
|
216
|
+
end
|
217
|
+
|
218
|
+
def new_thing
|
219
|
+
Marshal.load(@thing)
|
214
220
|
end
|
215
221
|
|
216
222
|
def corner(args)
|
@@ -232,8 +238,9 @@ module JennCad
|
|
232
238
|
from: args[:from],
|
233
239
|
to: args[:to],
|
234
240
|
a: args[:a],
|
235
|
-
direction: @direction
|
236
|
-
|
241
|
+
direction: @direction,
|
242
|
+
thing: thing,
|
243
|
+
)
|
237
244
|
|
238
245
|
_, ox, oy, x, y = rc.positions
|
239
246
|
@lpos[:x] += x + ox
|
@@ -292,7 +299,7 @@ module JennCad
|
|
292
299
|
return
|
293
300
|
end
|
294
301
|
|
295
|
-
@steps << Line.new(start_point: { x: @lpos[:x], y: @lpos[:y] }, end_point: { x: @lpos[:x] + x, y: @lpos[:y] + y }, angle: @angle, current_angle: @current_angle, direction: @direction, l: l
|
302
|
+
@steps << Line.new(start_point: { x: @lpos[:x], y: @lpos[:y] }, end_point: { x: @lpos[:x] + x, y: @lpos[:y] + y }, angle: @angle, current_angle: @current_angle, direction: @direction, l: l, thing: thing)
|
296
303
|
|
297
304
|
add_lpos({x: x, y: y})
|
298
305
|
end
|
data/lib/jenncad/features.rb
CHANGED
data/lib/jenncad/part.rb
CHANGED
@@ -3,9 +3,13 @@ module JennCad
|
|
3
3
|
class Part < Thing
|
4
4
|
|
5
5
|
def to_openscad
|
6
|
-
a = Aggregation.new(self.class.to_s, self.
|
6
|
+
a = Aggregation.new(self.class.to_s, self.get_contents)
|
7
7
|
a.transformations = @transformations
|
8
|
-
|
8
|
+
if self.has_explicit_color?
|
9
|
+
a.color(self.color)
|
10
|
+
else
|
11
|
+
a.color(:auto)
|
12
|
+
end
|
9
13
|
a
|
10
14
|
end
|
11
15
|
|
@@ -7,21 +7,29 @@ module JennCad::Primitives
|
|
7
7
|
else
|
8
8
|
@parts = parts
|
9
9
|
end
|
10
|
+
if parts.first && parts.first.respond_to?(:debug?) && parts.first.debug?
|
11
|
+
$log.debug("Creating new #{self.class} for part #{parts}")
|
12
|
+
end
|
13
|
+
|
10
14
|
@parent = @parts.first.parent
|
15
|
+
|
11
16
|
after_add
|
12
17
|
end
|
13
18
|
|
14
19
|
def add_or_new(part)
|
15
20
|
case @transformations
|
16
21
|
when nil, []
|
22
|
+
$log.debug("adding new part to existing boolean object") if part && part.debug?
|
17
23
|
add(part)
|
18
24
|
self
|
19
25
|
else
|
26
|
+
$log.debug("add_or_new: creating new boolean object") if part.debug?
|
20
27
|
self.class.new(self, part)
|
21
28
|
end
|
22
29
|
end
|
23
30
|
|
24
31
|
def add(part)
|
32
|
+
return if part.nil?
|
25
33
|
@parts << part
|
26
34
|
after_add
|
27
35
|
end
|
@@ -41,25 +49,25 @@ module JennCad::Primitives
|
|
41
49
|
end
|
42
50
|
|
43
51
|
def inherit_z
|
44
|
-
heights = @parts.map{|l| l.calc_z.
|
52
|
+
heights = @parts.map{|l| l.calc_z.to_d}.uniq
|
45
53
|
if heights.size > 1
|
46
54
|
total_heights = []
|
47
55
|
@parts.each do |p|
|
48
|
-
total_heights << p.z.
|
56
|
+
total_heights << p.z.to_d + p.calc_z.to_d
|
49
57
|
end
|
50
58
|
@z = total_heights.max
|
51
59
|
@calc_z = heights.min
|
52
60
|
else
|
53
|
-
@calc_z = heights.first.
|
61
|
+
@calc_z = heights.first.to_d
|
54
62
|
@z = @parts.map(&:z).compact.max
|
55
63
|
end
|
56
64
|
end
|
57
65
|
|
58
66
|
def inherit_zref
|
59
67
|
return if @parts.first == nil
|
60
|
-
#return if @parts.first.z.
|
68
|
+
#return if @parts.first.z.to_d == 0.0
|
61
69
|
get_primitives(@parts[1..-1]).flatten.each do |part|
|
62
|
-
if part.z.
|
70
|
+
if part.z.to_d == 0.0
|
63
71
|
part.set_option :zref, @parts.first
|
64
72
|
end
|
65
73
|
end
|
@@ -82,6 +82,13 @@ module JennCad::Primitives
|
|
82
82
|
set_anchor :top_right, x: right, y: top
|
83
83
|
set_anchor :bottom_left, x: left, y: bottom
|
84
84
|
set_anchor :bottom_right, x: right, y: bottom
|
85
|
+
if @opts[:center_z]
|
86
|
+
set_anchor :bottom_face, z: -@z/2.0
|
87
|
+
set_anchor :top_face, z: @z/2.0
|
88
|
+
else
|
89
|
+
set_anchor :bottom_face, z: 0
|
90
|
+
set_anchor :top_face, z: @z
|
91
|
+
end
|
85
92
|
|
86
93
|
# we need to re-do the inner ones, if they were defined
|
87
94
|
if @inner_anchor_defs && @inner_anchor_defs.size > 0
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module JennCad::Primitives
|
2
2
|
class Cylinder < Primitive
|
3
|
-
attr_accessor :d, :d1, :d2, :r, :fn
|
3
|
+
attr_accessor :d, :d1, :d2, :r, :fn, :anchors
|
4
4
|
def initialize(args)
|
5
5
|
if args.kind_of?(Array) && args[0].kind_of?(Hash)
|
6
6
|
args = args.first
|
@@ -24,6 +24,7 @@ module JennCad::Primitives
|
|
24
24
|
r2: nil,
|
25
25
|
z: nil,
|
26
26
|
r: 0,
|
27
|
+
cz: false,
|
27
28
|
margins: {
|
28
29
|
r: 0,
|
29
30
|
d: 0,
|
@@ -41,6 +42,35 @@ module JennCad::Primitives
|
|
41
42
|
handle_radius_diameter
|
42
43
|
handle_fn
|
43
44
|
super(args)
|
45
|
+
set_anchors
|
46
|
+
end
|
47
|
+
|
48
|
+
def set_anchors
|
49
|
+
@anchors = {} # reset anchors
|
50
|
+
if @opts[:d]
|
51
|
+
rad = @opts[:d] / 2.0
|
52
|
+
else
|
53
|
+
rad = @opts[:r]
|
54
|
+
end
|
55
|
+
|
56
|
+
# Similar to cube
|
57
|
+
set_anchor :left, x: -rad
|
58
|
+
set_anchor :right, x: rad
|
59
|
+
set_anchor :top, y: rad
|
60
|
+
set_anchor :bottom, y: -rad
|
61
|
+
|
62
|
+
# TODO: figure out if we also want to have "corners"
|
63
|
+
# - possibly move it like a cube
|
64
|
+
# - points at 45 ° angles might not be that useful unless you can get the point on the circle at a given angle
|
65
|
+
# - inner/outer points could be useful for small $fn values
|
66
|
+
|
67
|
+
if @opts[:cz]
|
68
|
+
set_anchor :bottom_face, z: -@z/2.0
|
69
|
+
set_anchor :top_face, z: @z/2.0
|
70
|
+
else
|
71
|
+
set_anchor :bottom_face, z: 0
|
72
|
+
set_anchor :top_face, z: @z
|
73
|
+
end
|
44
74
|
end
|
45
75
|
|
46
76
|
def openscad_params
|
@@ -60,20 +90,22 @@ module JennCad::Primitives
|
|
60
90
|
# Centers the cylinder around it's center point by height
|
61
91
|
# This will transform the cylinder around the center point.
|
62
92
|
def cz
|
93
|
+
@opts[:cz] = true
|
63
94
|
@transformations << Move.new(z: -@z / 2.0)
|
95
|
+
set_anchors
|
64
96
|
self
|
65
97
|
end
|
66
98
|
|
67
99
|
def handle_fn
|
68
100
|
case @opts[:fn]
|
69
101
|
when nil, 0
|
70
|
-
$fn =
|
102
|
+
$fn = auto_dn!
|
71
103
|
else
|
72
104
|
@fn = @opts[:fn]
|
73
105
|
end
|
74
106
|
end
|
75
107
|
|
76
|
-
def
|
108
|
+
def auto_dn!
|
77
109
|
case @d
|
78
110
|
when (16..)
|
79
111
|
@fn = (@d*4).ceil
|
@@ -85,25 +117,25 @@ module JennCad::Primitives
|
|
85
117
|
def handle_radius_diameter
|
86
118
|
case @opts[:d]
|
87
119
|
when 0, nil
|
88
|
-
@r = @opts[:r].
|
120
|
+
@r = @opts[:r].to_d + @opts[:margins][:r].to_d
|
89
121
|
@d = @r * 2.0
|
90
122
|
else
|
91
|
-
@d = @opts[:d].
|
123
|
+
@d = @opts[:d].to_d + @opts[:margins][:d].to_d
|
92
124
|
@r = @d / 2.0
|
93
125
|
end
|
94
126
|
|
95
127
|
case @opts[:d1]
|
96
128
|
when 0, nil
|
97
129
|
else
|
98
|
-
@d1 = @opts[:d1].
|
99
|
-
@d2 = @opts[:d2].
|
130
|
+
@d1 = @opts[:d1].to_d + @opts[:margins][:d].to_d
|
131
|
+
@d2 = @opts[:d2].to_d + @opts[:margins][:d].to_d
|
100
132
|
end
|
101
133
|
|
102
134
|
case @opts[:r1]
|
103
135
|
when 0, nil
|
104
136
|
else
|
105
|
-
@d1 = 2 * @opts[:r1].
|
106
|
-
@d2 = 2 * @opts[:r2].
|
137
|
+
@d1 = 2 * @opts[:r1].to_d + @opts[:margins][:d].to_d
|
138
|
+
@d2 = 2 * @opts[:r2].to_d + @opts[:margins][:d].to_d
|
107
139
|
end
|
108
140
|
end
|
109
141
|
|
@@ -5,14 +5,14 @@ module JennCad::Primitives
|
|
5
5
|
end
|
6
6
|
|
7
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]
|
8
|
+
@x = @opts[:x].to_d + @opts[:margins][:x].to_d
|
9
|
+
@y = @opts[:y].to_d + @opts[:margins][:y].to_d
|
10
|
+
@z = @opts[:z].to_d + @opts[:margins][:z].to_d
|
11
11
|
end
|
12
12
|
|
13
13
|
def handle_diameter
|
14
|
-
@d = opts[:d]
|
15
|
-
@r = opts[:r]
|
14
|
+
@d = opts[:d].to_d
|
15
|
+
@r = opts[:r].to_d
|
16
16
|
if @d
|
17
17
|
@r = @d/2.0
|
18
18
|
elsif @r
|
@@ -36,10 +36,25 @@ module JennCad::Primitives
|
|
36
36
|
@d = @opts[:d]
|
37
37
|
@a = @opts[:a]
|
38
38
|
@h = @opts[:h]
|
39
|
-
@r = @opts[:r]
|
39
|
+
@r = @opts[:r] || nil
|
40
|
+
if @r
|
41
|
+
@d = @r * 2
|
42
|
+
end
|
40
43
|
@fn = @opts[:fn]
|
41
44
|
@len_x = @opts[:x]
|
42
45
|
@len_y = @opts[:y]
|
46
|
+
tx = @opts[:tx] || @opts[:total_x] || nil
|
47
|
+
ty = @opts[:ty] || @opts[:total_y] || nil
|
48
|
+
if tx
|
49
|
+
@len_x = tx - @d
|
50
|
+
end
|
51
|
+
if ty
|
52
|
+
@len_y = ty - @d
|
53
|
+
end
|
54
|
+
|
55
|
+
# TODO: this needs anchors like cube
|
56
|
+
# TODO: color on this needs to apply to hull, not on the cylinders.
|
57
|
+
|
43
58
|
end
|
44
59
|
|
45
60
|
def to_openscad
|
@@ -64,16 +79,16 @@ module JennCad::Primitives
|
|
64
79
|
end
|
65
80
|
|
66
81
|
def end_vector
|
67
|
-
if @a.
|
82
|
+
if @a.to_d == 0.0
|
68
83
|
return [@len_x, 0] if @len_x
|
69
84
|
return [0, @len_y] if @len_y
|
70
85
|
end
|
71
86
|
if @len_x
|
72
|
-
x = cos(PI*@a/180.0)*@len_x.
|
73
|
-
y = sin(PI*@a/180.0)*@len_x.
|
87
|
+
x = cos(PI*@a/180.0)*@len_x.to_d
|
88
|
+
y = sin(PI*@a/180.0)*@len_x.to_d
|
74
89
|
else
|
75
|
-
x = -1* sin(PI*@a/180.0)*@len_y.
|
76
|
-
y = cos(PI*@a/180.0)*@len_y.
|
90
|
+
x = -1* sin(PI*@a/180.0)*@len_y.to_d
|
91
|
+
y = cos(PI*@a/180.0)*@len_y.to_d
|
77
92
|
end
|
78
93
|
[x,y]
|
79
94
|
end
|
@@ -2,13 +2,13 @@ module JennCad::Primitives
|
|
2
2
|
class SubtractObject < BooleanObject
|
3
3
|
def inherit_z
|
4
4
|
@z = 0
|
5
|
-
@calc_z = parts.first.calc_z.
|
5
|
+
@calc_z = parts.first.calc_z.to_d
|
6
6
|
|
7
7
|
only_additives_of(@parts).each do |p|
|
8
8
|
if option(:debug)
|
9
9
|
$log.debug "inherit_z checks for: #{p}"
|
10
10
|
end
|
11
|
-
z = p.z.
|
11
|
+
z = p.z.to_d
|
12
12
|
@z = z if z > @z
|
13
13
|
end
|
14
14
|
$log.debug "inherit_z called, biggest z found: #{@z}" if option(:debug)
|
@@ -80,7 +80,7 @@ module JennCad::Primitives
|
|
80
80
|
part.opts[:margins][:z] += 0.004
|
81
81
|
# part.z+=0.004
|
82
82
|
part.mz(-0.002)
|
83
|
-
elsif part.calc_z.
|
83
|
+
elsif part.calc_z.to_d+part.calc_h.to_d == compare_h
|
84
84
|
# puts "z fighting at top: #{compare_h}"
|
85
85
|
#part.z+=0.004
|
86
86
|
part.opts[:margins][:z] += 0.004
|
data/lib/jenncad/shortcuts.rb
CHANGED
@@ -92,13 +92,23 @@ module JennCad
|
|
92
92
|
|
93
93
|
private
|
94
94
|
def boolean_operation(part, klass)
|
95
|
+
if part.respond_to? :transformations
|
96
|
+
# Clone the part in place
|
97
|
+
part = part.fix
|
98
|
+
end
|
99
|
+
|
95
100
|
case self
|
96
101
|
when nil
|
97
102
|
part
|
98
103
|
when klass
|
99
104
|
add_or_new(part)
|
100
105
|
else
|
101
|
-
|
106
|
+
own_part = if self.respond_to? :transformations
|
107
|
+
self.fix # clone self
|
108
|
+
else
|
109
|
+
self
|
110
|
+
end
|
111
|
+
klass.new(own_part,part)
|
102
112
|
end
|
103
113
|
end
|
104
114
|
end
|
data/lib/jenncad/thing.rb
CHANGED
@@ -20,6 +20,7 @@ module JennCad
|
|
20
20
|
@anchors = {}
|
21
21
|
@parent = args[:parent]
|
22
22
|
@opts ||= args
|
23
|
+
@cache = nil
|
23
24
|
end
|
24
25
|
|
25
26
|
def option(key)
|
@@ -32,6 +33,23 @@ module JennCad
|
|
32
33
|
@opts[key] = val
|
33
34
|
end
|
34
35
|
|
36
|
+
def set_flag(key)
|
37
|
+
set_option(key, true)
|
38
|
+
end
|
39
|
+
|
40
|
+
def unset_flag(key)
|
41
|
+
set_option(key, false)
|
42
|
+
end
|
43
|
+
|
44
|
+
def debug?
|
45
|
+
option(:debug) || false
|
46
|
+
end
|
47
|
+
|
48
|
+
def fixate
|
49
|
+
Marshal.load(Marshal.dump(self))
|
50
|
+
end
|
51
|
+
alias :fix :fixate
|
52
|
+
|
35
53
|
def set_parent(parent)
|
36
54
|
@parent = parent
|
37
55
|
self
|
@@ -39,13 +57,19 @@ module JennCad
|
|
39
57
|
|
40
58
|
def anchor(name, thing=nil)
|
41
59
|
if thing
|
42
|
-
|
60
|
+
res = thing.anchor(name)
|
61
|
+
return res unless res.nil?
|
43
62
|
end
|
44
63
|
@anchors ||= {}
|
45
64
|
if anch = @anchors[name]
|
46
65
|
return anch
|
47
66
|
elsif @parent
|
48
67
|
return @parent.anchor(name)
|
68
|
+
elsif self.respond_to? :get_contents
|
69
|
+
con = get_contents
|
70
|
+
if con.respond_to? :anchor
|
71
|
+
con.anchor(name)
|
72
|
+
end
|
49
73
|
end
|
50
74
|
end
|
51
75
|
alias :a :anchor
|
@@ -57,6 +81,22 @@ module JennCad
|
|
57
81
|
end
|
58
82
|
alias :sa :set_anchor
|
59
83
|
|
84
|
+
def set_anchor_from(name, new_name, args={})
|
85
|
+
a = anchor(name).dup
|
86
|
+
if !a
|
87
|
+
log.error "set_anchor_from couldn't find anchor #{name}"
|
88
|
+
return
|
89
|
+
end
|
90
|
+
|
91
|
+
[:x, :y, :z, :xy, :xz, :xyz, :yz].each do |key|
|
92
|
+
a[key] ||= 0.to_d
|
93
|
+
args[key] ||= 0.to_d
|
94
|
+
a[key] += args[key]
|
95
|
+
end
|
96
|
+
set_anchor new_name, a
|
97
|
+
end
|
98
|
+
alias :saf :set_anchor_from
|
99
|
+
|
60
100
|
def auto_extrude
|
61
101
|
ret = self.extrude
|
62
102
|
ret.set_option(:auto_extrude, true)
|
@@ -86,7 +126,7 @@ module JennCad
|
|
86
126
|
case self
|
87
127
|
when UnionObject
|
88
128
|
ref = self.parts.first
|
89
|
-
rz = self.z.
|
129
|
+
rz = self.z.to_d + self.calc_h.to_d
|
90
130
|
when BooleanObject
|
91
131
|
ref = self.parts.first
|
92
132
|
rz = ref.calc_z + ref.calc_h
|
@@ -114,7 +154,7 @@ module JennCad
|
|
114
154
|
alias :fy :flip_y
|
115
155
|
|
116
156
|
def radians(a)
|
117
|
-
a.
|
157
|
+
a.to_d/180.0*PI
|
118
158
|
end
|
119
159
|
|
120
160
|
# experiment
|
@@ -174,21 +214,43 @@ module JennCad
|
|
174
214
|
end
|
175
215
|
|
176
216
|
def move(args={})
|
217
|
+
return self if args.nil? or args.empty?
|
218
|
+
|
177
219
|
if args.kind_of? Array
|
178
220
|
x,y,z = args
|
179
221
|
return move(x:x, y:y, z:z)
|
180
222
|
end
|
181
223
|
args = parse_xyz_shortcuts(args)
|
182
224
|
|
225
|
+
if args[:x].to_d == 0.0 && args[:y].to_d == 0.0 && args[:z].to_d == 0.0
|
226
|
+
return self
|
227
|
+
end
|
228
|
+
|
183
229
|
@transformations ||= []
|
184
230
|
if args[:prepend]
|
185
231
|
@transformations.prepend(Move.new(args))
|
186
232
|
else
|
187
|
-
@transformations
|
233
|
+
lt = @transformations.last
|
234
|
+
|
235
|
+
chain = if args[:chain]
|
236
|
+
args[:chain]
|
237
|
+
else
|
238
|
+
$jenncad_profile.chain_moves
|
239
|
+
end
|
240
|
+
|
241
|
+
if lt && lt.class == Move && chain == false
|
242
|
+
$log.debug "#{self} at move: Adding to previous move #{lt.inspect} , args: #{args}" if self.debug?
|
243
|
+
lt.x += args[:x].to_d
|
244
|
+
lt.y += args[:y].to_d
|
245
|
+
lt.z += args[:z].to_d
|
246
|
+
else
|
247
|
+
$log.debug "#{self} at move: Adding move of #{args} to transformations" if self.debug?
|
248
|
+
@transformations << Move.new(args)
|
249
|
+
end
|
188
250
|
end
|
189
|
-
@calc_x += args[:x].
|
190
|
-
@calc_y += args[:y].
|
191
|
-
@calc_z += args[:z].
|
251
|
+
@calc_x += args[:x].to_d
|
252
|
+
@calc_y += args[:y].to_d
|
253
|
+
@calc_z += args[:z].to_d
|
192
254
|
self
|
193
255
|
end
|
194
256
|
alias :translate :move
|
@@ -207,27 +269,39 @@ module JennCad
|
|
207
269
|
end
|
208
270
|
|
209
271
|
# move to anchor
|
210
|
-
def movea(key, thing=nil)
|
272
|
+
def movea(key, thing=nil, args={})
|
273
|
+
if thing.kind_of? Hash # if you leave out thing, args may be interpreted as thing
|
274
|
+
args = thing
|
275
|
+
thing = nil
|
276
|
+
end
|
277
|
+
|
211
278
|
an = anchor(key, thing)
|
279
|
+
|
212
280
|
unless an
|
213
281
|
$log.error "Error: Anchor #{key} not found"
|
214
282
|
$log.error "Available anchors: #{@anchors}"
|
215
283
|
return self
|
216
284
|
else
|
217
|
-
|
285
|
+
m = an.dup
|
286
|
+
if args[:chain]
|
287
|
+
m[:chain] = args[:chain]
|
288
|
+
end
|
289
|
+
if args[:inverted]
|
290
|
+
self.movei(m)
|
291
|
+
else
|
292
|
+
self.move(m)
|
293
|
+
end
|
218
294
|
end
|
219
295
|
end
|
220
296
|
|
221
297
|
# move to anchor - inverted
|
222
|
-
def moveai(key, thing=nil)
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
$log.error "Available anchors: #{@anchors}"
|
227
|
-
return self
|
228
|
-
else
|
229
|
-
self.movei(an.dup)
|
298
|
+
def moveai(key, thing=nil, args={})
|
299
|
+
if thing.kind_of? Hash # if you leave out thing, args may be interpreted as thing
|
300
|
+
args = thing
|
301
|
+
thing = nil
|
230
302
|
end
|
303
|
+
args[:inverted] = true
|
304
|
+
movea(key, thing, args)
|
231
305
|
end
|
232
306
|
|
233
307
|
|
@@ -264,6 +338,7 @@ module JennCad
|
|
264
338
|
to[key] = args[key]*-1
|
265
339
|
end
|
266
340
|
end
|
341
|
+
to[:chain] = args[:chain]
|
267
342
|
move(to)
|
268
343
|
end
|
269
344
|
|
@@ -327,7 +402,7 @@ module JennCad
|
|
327
402
|
end
|
328
403
|
|
329
404
|
def top_of(other_object)
|
330
|
-
self.move(z:other_object.z+other_object.calc_z.
|
405
|
+
self.move(z:other_object.z+other_object.calc_z.to_d)
|
331
406
|
end
|
332
407
|
|
333
408
|
def on_top_of(other_object)
|
@@ -341,36 +416,14 @@ module JennCad
|
|
341
416
|
def get_children(item, stop_at)
|
342
417
|
res = [item]
|
343
418
|
if item.respond_to?(:parts) && item.parts != nil
|
344
|
-
item.parts.each do |
|
345
|
-
unless stop_at != nil &&
|
346
|
-
res << get_children(
|
419
|
+
item.parts.each do |pa|
|
420
|
+
unless stop_at != nil && pa.kind_of?(stop_at)
|
421
|
+
res << get_children(pa, stop_at)
|
347
422
|
end
|
348
423
|
end
|
349
424
|
end
|
350
425
|
res
|
351
426
|
end
|
352
|
-
=begin def make_openscad_compatible
|
353
|
-
make_openscad_compatible!(self)
|
354
|
-
end
|
355
|
-
|
356
|
-
def make_openscad_compatible!(item)
|
357
|
-
if item.respond_to?(:parts) && item.parts != nil
|
358
|
-
item.parts.each_with_index do |part, i|
|
359
|
-
if part.respond_to? :to_openscad
|
360
|
-
item.parts[i] = part.to_openscad
|
361
|
-
else
|
362
|
-
item.parts[i] = part.make_openscad_compatible
|
363
|
-
end
|
364
|
-
end
|
365
|
-
elsif item.respond_to? :part
|
366
|
-
item = item.part.make_openscad_compatible
|
367
|
-
end
|
368
|
-
if item.respond_to? :to_openscad
|
369
|
-
item = item.to_openscad
|
370
|
-
end
|
371
|
-
item
|
372
|
-
end
|
373
|
-
=end
|
374
427
|
|
375
428
|
def inherit_color(other)
|
376
429
|
self.set_option(:color, other.option(:color))
|
@@ -386,11 +439,14 @@ module JennCad
|
|
386
439
|
|
387
440
|
def only_color?(parts, lvl=0)
|
388
441
|
return true if parts == nil
|
442
|
+
unless parts.kind_of? Array
|
443
|
+
parts = [parts]
|
444
|
+
end
|
389
445
|
|
390
446
|
parts.each do |part|
|
391
|
-
#
|
447
|
+
#puts " " * lvl + "[only_color?] #{part}"
|
392
448
|
if part.has_explicit_color?
|
393
|
-
#
|
449
|
+
#puts " " * lvl + "found explicit color here: #{part.color}"
|
394
450
|
return false
|
395
451
|
end
|
396
452
|
if !only_color?(part.parts, lvl+1)
|
@@ -406,14 +462,14 @@ module JennCad
|
|
406
462
|
parts.each do |part|
|
407
463
|
unless part.has_explicit_color?
|
408
464
|
if only_color?(part.parts, lvl+1)
|
409
|
-
#
|
465
|
+
#puts " " * lvl + "children have no explicit color, setting it here"
|
410
466
|
part.set_auto_color(col)
|
411
467
|
else
|
412
|
-
#
|
468
|
+
#puts " " * lvl + "[set_auto_color_for_children] #{part}"
|
413
469
|
set_auto_color_for_children(col, part.parts, lvl+1)
|
414
470
|
end
|
415
471
|
else
|
416
|
-
#
|
472
|
+
#puts " " * lvl + "[set_auto_color_for_children] this part has a color #{part.color}, ignoring their children"
|
417
473
|
end
|
418
474
|
|
419
475
|
end
|
@@ -467,6 +523,8 @@ module JennCad
|
|
467
523
|
return "##{args}"
|
468
524
|
when String
|
469
525
|
return args
|
526
|
+
when Symbol
|
527
|
+
return args.to_s
|
470
528
|
end
|
471
529
|
nil
|
472
530
|
end
|
@@ -489,8 +547,15 @@ module JennCad
|
|
489
547
|
|
490
548
|
def get_contents
|
491
549
|
return @parts unless @parts.nil?
|
550
|
+
|
551
|
+
if @cache
|
552
|
+
return @cache
|
553
|
+
end
|
554
|
+
|
492
555
|
if self.respond_to? :part
|
493
|
-
|
556
|
+
# cache things to prevent calling the code in #part multiple times
|
557
|
+
@cache = part
|
558
|
+
return @cache
|
494
559
|
end
|
495
560
|
end
|
496
561
|
|
@@ -503,6 +568,9 @@ module JennCad
|
|
503
568
|
|
504
569
|
def find_calculated_h(parts)
|
505
570
|
return if parts == nil
|
571
|
+
unless parts.kind_of? Array
|
572
|
+
parts = [parts]
|
573
|
+
end
|
506
574
|
parts.each do |part|
|
507
575
|
if z = calculated_h
|
508
576
|
return z
|
@@ -513,6 +581,10 @@ module JennCad
|
|
513
581
|
|
514
582
|
def set_heights_for_auto_extrude(parts, parent=nil)
|
515
583
|
return if parts.nil?
|
584
|
+
unless parts.kind_of? Array
|
585
|
+
parts = [parts]
|
586
|
+
end
|
587
|
+
|
516
588
|
parts.each do |part|
|
517
589
|
if part.option(:auto_extrude)
|
518
590
|
part.z = parent.calculated_h
|
@@ -561,7 +633,7 @@ module JennCad
|
|
561
633
|
end
|
562
634
|
|
563
635
|
def referenced_z
|
564
|
-
return false if @z.
|
636
|
+
return false if @z.to_d != 0.0
|
565
637
|
return option(:zref) if option(:zref)
|
566
638
|
return false
|
567
639
|
end
|
@@ -576,7 +648,7 @@ module JennCad
|
|
576
648
|
when nil, false
|
577
649
|
@z + z_margin
|
578
650
|
else
|
579
|
-
ref.z.
|
651
|
+
ref.z.to_d + ref.z_margin.to_d
|
580
652
|
end
|
581
653
|
end
|
582
654
|
|
@@ -585,7 +657,7 @@ module JennCad
|
|
585
657
|
when nil, {}
|
586
658
|
0.0
|
587
659
|
else
|
588
|
-
m[:z].
|
660
|
+
m[:z].to_d
|
589
661
|
end
|
590
662
|
end
|
591
663
|
|
data/lib/jenncad/version.rb
CHANGED
data/lib/jenncad.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jenncad
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.0.pre.
|
4
|
+
version: 1.0.0.pre.alpha15
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jennifer Glauche
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-05-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: geo3d
|
@@ -122,6 +122,7 @@ files:
|
|
122
122
|
- lib/jenncad/features/climb.rb
|
123
123
|
- lib/jenncad/features/cuttable.rb
|
124
124
|
- lib/jenncad/features/feature.rb
|
125
|
+
- lib/jenncad/features/multiples_of.rb
|
125
126
|
- lib/jenncad/features/openscad_include.rb
|
126
127
|
- lib/jenncad/features/path.rb
|
127
128
|
- lib/jenncad/features/stl_import.rb
|