jenncad 1.0.0.pre.alpha1 → 1.0.0.pre.alpha4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +83 -0
- data/jenncad.gemspec +2 -1
- data/lib/jenncad/default_profile.rb +2 -2
- data/lib/jenncad/exporters/openscad.rb +260 -0
- data/lib/jenncad/features/aggregation.rb +16 -0
- data/lib/jenncad/features/climb.rb +95 -0
- data/lib/jenncad/features/cuttable.rb +35 -0
- data/lib/jenncad/features/feature.rb +4 -0
- data/lib/jenncad/{primitives → features}/openscad_include.rb +1 -1
- data/lib/jenncad/features/stl_import.rb +10 -0
- data/lib/jenncad/features.rb +11 -0
- data/lib/jenncad/part.rb +7 -4
- data/lib/jenncad/patches/array.rb +28 -8
- data/lib/jenncad/primitives/boolean_object.rb +11 -1
- data/lib/jenncad/primitives/cube.rb +26 -18
- data/lib/jenncad/primitives/cylinder.rb +65 -9
- data/lib/jenncad/primitives/rotate_extrude.rb +1 -1
- data/lib/jenncad/primitives/rounded_cube.rb +8 -10
- data/lib/jenncad/primitives/subtract_object.rb +17 -13
- data/lib/jenncad/primitives.rb +20 -0
- data/lib/jenncad/shortcuts.rb +30 -35
- data/lib/jenncad/thing.rb +137 -41
- data/lib/jenncad/transformation/color.rb +179 -0
- data/lib/jenncad/transformation/scale.rb +2 -0
- data/lib/jenncad/version.rb +1 -1
- data/lib/jenncad.rb +5 -30
- metadata +31 -11
- data/lib/jenncad/jenncad.rb +0 -3
- data/lib/jenncad/openscad.rb +0 -274
- data/lib/jenncad/primitives/aggregation.rb +0 -12
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ea1fa04592f59d248c5801c3b645f16429bd7ae9f0b754aa467c8a401c89ec4b
|
4
|
+
data.tar.gz: 4df185f63b22b5945784cf820b4af937e4fbc660875f36093bbd5ebe9baa2aa9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '0809987ec1b33518b17402acb27b659da2dc7b97ee304d1549abd857ae4448e0342d6ee4523e8d2277d7ce765e1278f996af9882b5da91b71c93acec8bd9ffd9'
|
7
|
+
data.tar.gz: e412b05272163c37096d36a44d83ac3d3c5ae07089d7d8d7236c1c53a263c24742566b691efbb5a03c9148960cb7734eb2859bc279e450e34c131fda2ae85af5
|
data/README.md
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
|
2
|
+
# jenncad
|
3
|
+
Create physical objects in Ruby, OpenScad export
|
4
|
+
|
5
|
+
This is a successor to my older project CrystalScad.
|
6
|
+
|
7
|
+
# Installation
|
8
|
+
|
9
|
+
A packaged release is not yet available, please build your own package in the meantime:
|
10
|
+
|
11
|
+
$ git clone git@github.com:jglauche/jenncad.git
|
12
|
+
$ cd jenncad
|
13
|
+
$ rake install
|
14
|
+
|
15
|
+
This will create a gem and a binary jenncad.
|
16
|
+
|
17
|
+
# Using Jenncad
|
18
|
+
|
19
|
+
**To create a new project directory, run:**
|
20
|
+
|
21
|
+
$ jenncad create meow
|
22
|
+
|
23
|
+
|
24
|
+
|
25
|
+
|
26
|
+
This will generate a directory meow/ and an executable ruby file meow.rb in its directory
|
27
|
+
|
28
|
+
$ cd meow
|
29
|
+
$ ./meow
|
30
|
+
|
31
|
+
This will generate a dummy project which generates a dummy cube as OpenSCAD output:
|
32
|
+
|
33
|
+
$ cat output/meow.scad
|
34
|
+
> $fn=64;
|
35
|
+
> translate([-5, -5, 0])cube([10, 10, 10.0]);
|
36
|
+
|
37
|
+
**Automatically refresh OpenSCAD output while developing**
|
38
|
+
|
39
|
+
Jenncad bundles the observr gem which will check if files were changed while developing. In the project directory run:
|
40
|
+
|
41
|
+
$ jenncad
|
42
|
+
This should display something like:
|
43
|
+
> refreshing...
|
44
|
+
> ok
|
45
|
+
> JennCad running, refreshing on file changes. Press ctrl+c to exit
|
46
|
+
|
47
|
+
**Note:** This does not check for new files in the project. You will have to restart it when you create a new part in a new file
|
48
|
+
|
49
|
+
**Create new part**
|
50
|
+
|
51
|
+
In your project directory, run:
|
52
|
+
|
53
|
+
$ jenncad new cat
|
54
|
+
part parts/cat.rb created. In your meow.rb add to class Meow:
|
55
|
+
def cat
|
56
|
+
Cat.new(config)
|
57
|
+
end
|
58
|
+
|
59
|
+
|
60
|
+
You will have to link the part to the project manually into the meow.rb file in your project directory. When you add it, your meow.rb should look like this:
|
61
|
+
|
62
|
+
#!/usr/bin/env ruby
|
63
|
+
require "jenncad"
|
64
|
+
include JennCad
|
65
|
+
|
66
|
+
class Meow < Project
|
67
|
+
def config
|
68
|
+
{}
|
69
|
+
end
|
70
|
+
|
71
|
+
def meow
|
72
|
+
cube(10,10,10)
|
73
|
+
end
|
74
|
+
|
75
|
+
def cat
|
76
|
+
Cat.new(config)
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
Meow.new.run
|
81
|
+
|
82
|
+
|
83
|
+
|
data/jenncad.gemspec
CHANGED
@@ -19,9 +19,10 @@ Gem::Specification.new do |gem|
|
|
19
19
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
20
20
|
gem.require_paths = ["lib"]
|
21
21
|
|
22
|
-
gem.required_ruby_version = ">= 2.
|
22
|
+
gem.required_ruby_version = ">= 2.6.0"
|
23
23
|
gem.add_runtime_dependency "geo3d"
|
24
24
|
gem.add_runtime_dependency "deep_merge"
|
25
25
|
gem.add_runtime_dependency "hanami-cli"
|
26
26
|
gem.add_runtime_dependency "activesupport"
|
27
|
+
gem.add_runtime_dependency "observr"
|
27
28
|
end
|
@@ -0,0 +1,260 @@
|
|
1
|
+
module JennCad::Exporters
|
2
|
+
class OpenScadObject
|
3
|
+
def initialize(cmd, args, children=[])
|
4
|
+
@command = cmd
|
5
|
+
@args = args
|
6
|
+
case children
|
7
|
+
when Array
|
8
|
+
@children = children
|
9
|
+
else
|
10
|
+
@children = [children]
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def nl
|
15
|
+
"\n"
|
16
|
+
end
|
17
|
+
|
18
|
+
def to_s
|
19
|
+
case @command
|
20
|
+
when nil
|
21
|
+
""
|
22
|
+
when :head
|
23
|
+
res = "$fn=64;"+nl
|
24
|
+
@children.each do |c|
|
25
|
+
res += c.to_s+nl
|
26
|
+
end
|
27
|
+
res
|
28
|
+
when :module
|
29
|
+
handle_module
|
30
|
+
when String, Symbol
|
31
|
+
handle_command
|
32
|
+
else
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def handle_module
|
37
|
+
res = "module #{@args}(){"+nl
|
38
|
+
res += tabs(1, @children.map{|c| c.handle_command(2) })
|
39
|
+
res += "}"
|
40
|
+
res
|
41
|
+
end
|
42
|
+
|
43
|
+
def handle_command(i=1)
|
44
|
+
case @children.size
|
45
|
+
when 0
|
46
|
+
"#{@command}(#{handle_args});"
|
47
|
+
when 1
|
48
|
+
"#{@command}(#{handle_args})#{@children.first.handle_command(i+1)}"
|
49
|
+
when (1..)
|
50
|
+
res = "#{@command}(#{handle_args}){"
|
51
|
+
res += nl
|
52
|
+
inner = @children.map do |c|
|
53
|
+
next if c == nil
|
54
|
+
c.handle_command(i+1)
|
55
|
+
end
|
56
|
+
res += tabs(i, inner.compact)
|
57
|
+
res += nl
|
58
|
+
res += tabs(i-1,["}"])+nl
|
59
|
+
res
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def tabs(i,a)
|
64
|
+
a.map{ |l|
|
65
|
+
" " * i + l
|
66
|
+
}.join(nl)
|
67
|
+
end
|
68
|
+
|
69
|
+
def handle_args
|
70
|
+
case @args
|
71
|
+
when String, Symbol
|
72
|
+
return "\"#{@args}\""
|
73
|
+
when Array
|
74
|
+
return @args.map do |l|
|
75
|
+
if l == nil
|
76
|
+
0
|
77
|
+
elsif l.kind_of? Array
|
78
|
+
l # skipping check of 2-dmin Arrays for now (used in multmatrix)
|
79
|
+
elsif l.to_i == l.to_f
|
80
|
+
l.to_i
|
81
|
+
else
|
82
|
+
l.to_f
|
83
|
+
end
|
84
|
+
end
|
85
|
+
when Hash
|
86
|
+
res = []
|
87
|
+
@args.each do |k,v|
|
88
|
+
if k.to_s == "fn"
|
89
|
+
k = "$fn"
|
90
|
+
end
|
91
|
+
if v == nil
|
92
|
+
next
|
93
|
+
end
|
94
|
+
if !v.kind_of?(Array) && !v.kind_of?(TrueClass) && !v.kind_of?(FalseClass) && v == v.to_i
|
95
|
+
v = v.to_i
|
96
|
+
end
|
97
|
+
if v.kind_of? String
|
98
|
+
q = "\""
|
99
|
+
else
|
100
|
+
q = ""
|
101
|
+
end
|
102
|
+
res << "#{k}=#{q}#{v}#{q}"
|
103
|
+
end
|
104
|
+
res.join(",").gsub("size=","")
|
105
|
+
else
|
106
|
+
""
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
class OpenScad
|
112
|
+
include ActiveSupport::Inflector
|
113
|
+
def initialize(part)
|
114
|
+
@imports = []
|
115
|
+
@modules = {}
|
116
|
+
@global_fn = 64
|
117
|
+
@object_tree = OpenScadObject.new(:head, nil, parse(part))
|
118
|
+
end
|
119
|
+
|
120
|
+
def save(file)
|
121
|
+
File.open(file,"w") do |f|
|
122
|
+
@imports.uniq.each do |val|
|
123
|
+
f.puts "use <#{val}.scad>\n"
|
124
|
+
end
|
125
|
+
|
126
|
+
@modules.each do |key, val|
|
127
|
+
f.puts val.to_s
|
128
|
+
end
|
129
|
+
f.puts @object_tree.to_s
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
def parse(part)
|
134
|
+
if part.respond_to? :to_openscad
|
135
|
+
part = part.to_openscad
|
136
|
+
end
|
137
|
+
|
138
|
+
if part.respond_to? :analyze_z_fighting
|
139
|
+
part = part.analyze_z_fighting
|
140
|
+
end
|
141
|
+
|
142
|
+
case part
|
143
|
+
when Array
|
144
|
+
part.map{ |p| parse(p) }
|
145
|
+
when JennCad::OpenScadImport
|
146
|
+
handle_import(part)
|
147
|
+
when JennCad::Aggregation
|
148
|
+
handle_aggregation(part)
|
149
|
+
when JennCad::UnionObject
|
150
|
+
bool('union', part)
|
151
|
+
when JennCad::SubtractObject
|
152
|
+
bool('difference', part)
|
153
|
+
when JennCad::IntersectionObject
|
154
|
+
bool('intersection', part)
|
155
|
+
when JennCad::HullObject
|
156
|
+
bool('hull', part)
|
157
|
+
when JennCad::Primitives::Circle
|
158
|
+
prim('circle', part)
|
159
|
+
when JennCad::Primitives::Cylinder
|
160
|
+
prim('cylinder', part)
|
161
|
+
when JennCad::Primitives::Sphere
|
162
|
+
prim('sphere', part)
|
163
|
+
when JennCad::Primitives::Cube
|
164
|
+
prim('cube', part)
|
165
|
+
when JennCad::Primitives::LinearExtrude
|
166
|
+
new_obj(part, :linear_extrude, part.openscad_params, parse(part.parts))
|
167
|
+
when JennCad::Primitives::RotateExtrude
|
168
|
+
new_obj(part, :rotate_extrude, part.openscad_params, parse(part.parts))
|
169
|
+
when JennCad::Primitives::Projection
|
170
|
+
new_obj(part, :projection, collect_params(part), parse(part.parts))
|
171
|
+
when JennCad::Primitives::Polygon
|
172
|
+
new_obj(part, :polygon, collect_params(part))
|
173
|
+
when JennCad::StlImport
|
174
|
+
new_obj(part, :import, collect_params(part))
|
175
|
+
when JennCad::Part
|
176
|
+
parse(part.part)
|
177
|
+
when nil
|
178
|
+
new_obj(part, nil)
|
179
|
+
else
|
180
|
+
puts "unknown part #{part.class}"
|
181
|
+
OpenScadObject.new(nil,nil)
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
def new_obj(part, cmd, args=nil, children=[])
|
186
|
+
transform(part) do
|
187
|
+
apply_color(part) do
|
188
|
+
OpenScadObject.new(cmd, args, children)
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
def bool(type, part)
|
194
|
+
new_obj(part, type, nil, parse(part.parts))
|
195
|
+
end
|
196
|
+
|
197
|
+
def prim(type, part)
|
198
|
+
new_obj(part, type, collect_params(part))
|
199
|
+
end
|
200
|
+
|
201
|
+
def collect_params(part)
|
202
|
+
if part.respond_to? :openscad_params
|
203
|
+
return part.openscad_params
|
204
|
+
end
|
205
|
+
res = {}
|
206
|
+
[:d, :h, :d1, :d2, :size, :fn, :points, :file].each do |var|
|
207
|
+
if part.respond_to? var
|
208
|
+
res[var] = part.send var
|
209
|
+
end
|
210
|
+
end
|
211
|
+
case res[:fn]
|
212
|
+
when @global_fn
|
213
|
+
res[:fn] = nil
|
214
|
+
else
|
215
|
+
end
|
216
|
+
res
|
217
|
+
end
|
218
|
+
|
219
|
+
def apply_color(part, &block)
|
220
|
+
return block.yield if part.nil? or part.color_or_fallback.nil?
|
221
|
+
OpenScadObject.new("color", part.color_or_fallback, block.yield)
|
222
|
+
end
|
223
|
+
|
224
|
+
def transform(part, &block)
|
225
|
+
return block.yield if part.transformations.nil?
|
226
|
+
|
227
|
+
case t = part.transformations.pop
|
228
|
+
when nil, []
|
229
|
+
block.yield
|
230
|
+
when JennCad::Move
|
231
|
+
OpenScadObject.new(:translate, t.coordinates, transform(part, &block))
|
232
|
+
when JennCad::Rotate, JennCad::Mirror
|
233
|
+
OpenScadObject.new(demodulize(t.class).downcase, t.coordinates, transform(part, &block))
|
234
|
+
when JennCad::Scale
|
235
|
+
OpenScadObject.new(:scale, t.scale, transform(part, &block))
|
236
|
+
when JennCad::Multmatrix
|
237
|
+
OpenScadObject.new(:multmatrix, t.m, transform(part, &block))
|
238
|
+
else
|
239
|
+
puts "unknown transformation #{t}"
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
def handle_aggregation(part, tabindex=0)
|
244
|
+
register_module(part) unless @modules[part.name]
|
245
|
+
transform(part) do
|
246
|
+
new_obj(part, part.name, nil)
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
# accept aggregation
|
251
|
+
def register_module(part)
|
252
|
+
@modules[part.name] = OpenScadObject.new(:module, part.name, parse(part.part))
|
253
|
+
end
|
254
|
+
|
255
|
+
def handle_import(part)
|
256
|
+
@imports << part.import
|
257
|
+
new_obj(part, part.name, part.args)
|
258
|
+
end
|
259
|
+
end
|
260
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module JennCad::Features
|
2
|
+
class Aggregation < Feature
|
3
|
+
attr_accessor :parts
|
4
|
+
|
5
|
+
def initialize(name=nil, part=nil)
|
6
|
+
super({})
|
7
|
+
@name = name
|
8
|
+
@parts = [part] # NOTE: single length arrayto make checking children easier
|
9
|
+
end
|
10
|
+
|
11
|
+
def part
|
12
|
+
@parts.first
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
module JennCad::Features
|
2
|
+
class Climb < Feature
|
3
|
+
def initialize(opts, block)
|
4
|
+
@opts = {
|
5
|
+
offset: :auto,
|
6
|
+
step: nil,
|
7
|
+
steps: nil,
|
8
|
+
bottom: nil,
|
9
|
+
top: nil,
|
10
|
+
z: nil,
|
11
|
+
}.deep_merge!(opts)
|
12
|
+
if @opts[:step].nil? && @opts[:steps].nil?
|
13
|
+
raise "please define at least one of :step or :steps for climb"
|
14
|
+
end
|
15
|
+
super(@opts)
|
16
|
+
@block = block
|
17
|
+
end
|
18
|
+
|
19
|
+
def z_or_referenced
|
20
|
+
case z = @opts[:z]
|
21
|
+
when nil
|
22
|
+
referenced_z.z
|
23
|
+
else
|
24
|
+
z
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def get_step(z)
|
29
|
+
case step = @opts[:step]
|
30
|
+
when nil, :auto, 0, 0.0
|
31
|
+
steps = @opts[:steps]
|
32
|
+
(z / steps).floor
|
33
|
+
else
|
34
|
+
step.to_f
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def get_offset(z)
|
39
|
+
case offset = @opts[:offset]
|
40
|
+
when :auto
|
41
|
+
step = get_step(z)
|
42
|
+
((z % step) + step) / 2.0
|
43
|
+
when nil, 0, 0.0
|
44
|
+
0.0
|
45
|
+
else
|
46
|
+
offset
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def climb_from_bottom(offset, step, n)
|
51
|
+
n.times.map{ |i| @block.yield.mz(offset+step*i) }.union
|
52
|
+
end
|
53
|
+
|
54
|
+
def climb_from_top(z, offset, step, n)
|
55
|
+
n.times.map{ |i| @block.yield.mz(z-offset-step*i) }.union
|
56
|
+
end
|
57
|
+
|
58
|
+
def to_openscad
|
59
|
+
ref_z = z_or_referenced
|
60
|
+
step = get_step(ref_z)
|
61
|
+
steps, top, bottom = @opts.values_at(:steps, :top, :bottom)
|
62
|
+
|
63
|
+
offset = get_offset(ref_z)
|
64
|
+
|
65
|
+
lo = (ref_z-offset*2).to_f % step.to_f
|
66
|
+
unless lo.to_f == 0.0
|
67
|
+
puts "[Warning]: climb has leftover offset #{lo}"
|
68
|
+
end
|
69
|
+
|
70
|
+
if steps
|
71
|
+
top = steps
|
72
|
+
bottom = steps
|
73
|
+
end
|
74
|
+
|
75
|
+
unless top or bottom
|
76
|
+
climb_from_bottom(offset, step, ((ref_z-offset*2) / step).floor + 1 )
|
77
|
+
else
|
78
|
+
res = nil
|
79
|
+
if top
|
80
|
+
res += climb_from_top(ref_z, offset, step, top)
|
81
|
+
end
|
82
|
+
if bottom
|
83
|
+
res += climb_from_bottom(offset, step, bottom)
|
84
|
+
end
|
85
|
+
res
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
90
|
+
|
91
|
+
def climb(args, &block)
|
92
|
+
Climb.new(args, block)
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module JennCad::Features
|
2
|
+
module Cuttable
|
3
|
+
def cut(args, &block)
|
4
|
+
if args[:x]
|
5
|
+
l = args[:x].min * @opts[:y] / 2.0
|
6
|
+
r = args[:x].max * @opts[:y] / 2.0
|
7
|
+
prepare_cut(l, r, &block).flip_x
|
8
|
+
elsif args[:y]
|
9
|
+
l = args[:y].min * @opts[:y] / 2.0
|
10
|
+
r = args[:y].max * @opts[:y] / 2.0
|
11
|
+
prepare_cut(l, r, &block).flip_y
|
12
|
+
elsif args[:z]
|
13
|
+
raise "cut for Z is not implemented yet"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def prepare_cut(l, r, &block)
|
18
|
+
part = block.call
|
19
|
+
if part.z.to_f > 0.0
|
20
|
+
part.opts[:margins][:z] = 0.2
|
21
|
+
if l == 0.0
|
22
|
+
part.mz(r+0.1)
|
23
|
+
else
|
24
|
+
part.mz(l+part.z.to_f-0.2)
|
25
|
+
end
|
26
|
+
else
|
27
|
+
part.opts[:margins][:z] = 0.2
|
28
|
+
part.z = l.abs + r.abs + 0.2
|
29
|
+
part.mz(-0.1)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require "jenncad/features/feature"
|
2
|
+
require "jenncad/features/aggregation"
|
3
|
+
require "jenncad/features/cuttable"
|
4
|
+
require "jenncad/features/openscad_include"
|
5
|
+
require "jenncad/features/climb"
|
6
|
+
require "jenncad/features/stl_import"
|
7
|
+
|
8
|
+
|
9
|
+
module JennCad
|
10
|
+
include Features
|
11
|
+
end
|
data/lib/jenncad/part.rb
CHANGED
@@ -2,13 +2,16 @@ module JennCad
|
|
2
2
|
# Part should be inherited from the user when making parts
|
3
3
|
class Part < Thing
|
4
4
|
|
5
|
-
def make_openscad_compatible
|
6
|
-
auto_color
|
7
|
-
a = Aggregation.new(self.class.to_s, make_openscad_compatible!(self.part))
|
5
|
+
def to_openscad #make_openscad_compatible
|
6
|
+
# auto_color
|
7
|
+
a = Aggregation.new(self.class.to_s, self.part) #make_openscad_compatible!(self.part))
|
8
8
|
a.transformations = @transformations
|
9
|
-
a.color(
|
9
|
+
a.color(:auto)
|
10
10
|
a
|
11
11
|
end
|
12
12
|
|
13
|
+
def part
|
14
|
+
end
|
15
|
+
|
13
16
|
end
|
14
17
|
end
|
@@ -12,18 +12,38 @@ class Array
|
|
12
12
|
else
|
13
13
|
res = part
|
14
14
|
end
|
15
|
-
|
16
|
-
res, z = res.move(z:z), z + res.z.to_f + 0.01 unless skip_z
|
15
|
+
res, z = res.mz(z), z + res.z.to_f unless skip_z
|
17
16
|
res
|
18
17
|
end
|
19
18
|
.union
|
20
19
|
end
|
21
20
|
|
22
|
-
def union
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
21
|
+
def union
|
22
|
+
UnionObject.new(self)
|
23
|
+
end
|
24
|
+
alias u union
|
25
|
+
|
26
|
+
def subtraction
|
27
|
+
SubtractObject.new(self)
|
28
28
|
end
|
29
|
+
alias subtract subtraction
|
30
|
+
alias sub subtraction
|
31
|
+
alias s subtraction
|
32
|
+
|
33
|
+
def intersection
|
34
|
+
IntersectionObject.new(self)
|
35
|
+
end
|
36
|
+
alias intersect intersection
|
37
|
+
alias i intersection
|
38
|
+
|
39
|
+
def hull
|
40
|
+
HullObject.new(self)
|
41
|
+
end
|
42
|
+
alias h hull
|
43
|
+
|
44
|
+
|
45
|
+
def random
|
46
|
+
self[Random.rand(size)]
|
47
|
+
end
|
48
|
+
|
29
49
|
end
|
@@ -10,6 +10,16 @@ module JennCad::Primitives
|
|
10
10
|
after_add
|
11
11
|
end
|
12
12
|
|
13
|
+
def add_or_new(part)
|
14
|
+
case @transformations
|
15
|
+
when nil, []
|
16
|
+
add(part)
|
17
|
+
self
|
18
|
+
else
|
19
|
+
self.class.new(self, part)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
13
23
|
def add(part)
|
14
24
|
@parts << part
|
15
25
|
after_add
|
@@ -39,7 +49,7 @@ module JennCad::Primitives
|
|
39
49
|
|
40
50
|
def inherit_zref
|
41
51
|
return if @parts.first == nil
|
42
|
-
return if @parts.first.z.to_f == 0.0
|
52
|
+
#return if @parts.first.z.to_f == 0.0
|
43
53
|
get_primitives(@parts[1..-1]).flatten.each do |part|
|
44
54
|
if part.z.to_f == 0.0
|
45
55
|
part.set_option :zref, @parts.first
|