jenncad 1.0.0.pre.alpha1 → 1.0.0.pre.alpha4
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 +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
|