jenncad 1.0.0.pre.alpha3 → 1.0.0.pre.alpha7
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/bin/jenncad +1 -1
- data/jenncad.gemspec +1 -1
- data/lib/jenncad/commands.rb +34 -11
- data/lib/jenncad/exporters/openscad.rb +13 -3
- data/lib/jenncad/features/aggregation.rb +6 -2
- data/lib/jenncad/features/stl_import.rb +10 -0
- data/lib/jenncad/features.rb +2 -0
- data/lib/jenncad/part.rb +3 -4
- data/lib/jenncad/primitives/cube.rb +26 -9
- data/lib/jenncad/primitives/cylinder.rb +29 -1
- data/lib/jenncad/primitives/linear_extrude.rb +7 -3
- data/lib/jenncad/primitives/rotate_extrude.rb +1 -1
- data/lib/jenncad/primitives/rounded_cube.rb +11 -7
- data/lib/jenncad/primitives/subtract_object.rb +1 -0
- data/lib/jenncad/shortcuts.rb +5 -1
- data/lib/jenncad/thing.rb +190 -25
- data/lib/jenncad/version.rb +1 -1
- metadata +9 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 59b41052c4c676ae59a808744715a5e10b1c1086350d4c7769b87d054f51d171
|
4
|
+
data.tar.gz: a620928785ad237699d0afff433912a8b5c5f6d765492d4d1f72d4d4d83fb962
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2118f2cff401f4874c6dda0f801cfda1666e0b032158e088ff83ecf24072654a7545fc4ecd9e245398d2de2497f7b363a7a2fe4db90856d87a9a2a60ff39816b
|
7
|
+
data.tar.gz: dd82a60377991ec146d6d9c259e19df75ee752b25eb1b44ed5cc2b33aea3f7b791726dd8ee12182ac323ad7902f75da5b8d5127858efa235d4792ac0755fa52e
|
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/bin/jenncad
CHANGED
@@ -7,4 +7,4 @@ JennCad::Commands.register "build", JennCad::Commands::Build
|
|
7
7
|
JennCad::Commands.register "new", JennCad::Commands::NewPart
|
8
8
|
JennCad::Commands.register "create", JennCad::Commands::NewProject
|
9
9
|
|
10
|
-
|
10
|
+
Dry::CLI.new(JennCad::Commands).call
|
data/jenncad.gemspec
CHANGED
@@ -22,7 +22,7 @@ Gem::Specification.new do |gem|
|
|
22
22
|
gem.required_ruby_version = ">= 2.6.0"
|
23
23
|
gem.add_runtime_dependency "geo3d"
|
24
24
|
gem.add_runtime_dependency "deep_merge"
|
25
|
-
gem.add_runtime_dependency "
|
25
|
+
gem.add_runtime_dependency "dry-cli"
|
26
26
|
gem.add_runtime_dependency "activesupport"
|
27
27
|
gem.add_runtime_dependency "observr"
|
28
28
|
end
|
data/lib/jenncad/commands.rb
CHANGED
@@ -1,8 +1,9 @@
|
|
1
1
|
module JennCad
|
2
2
|
module Commands
|
3
|
-
extend
|
3
|
+
extend Dry::CLI::Registry
|
4
|
+
MAGIC = "jenncad-append-project-magic"
|
4
5
|
|
5
|
-
class Run <
|
6
|
+
class Run < Dry::CLI::Command
|
6
7
|
argument :name, required: false
|
7
8
|
|
8
9
|
def guess_executable(dir=Dir.pwd)
|
@@ -87,7 +88,7 @@ module JennCad
|
|
87
88
|
end
|
88
89
|
end
|
89
90
|
|
90
|
-
class NewPart <
|
91
|
+
class NewPart < Dry::CLI::Command
|
91
92
|
include ActiveSupport::Inflector
|
92
93
|
desc "creates a new part in a project"
|
93
94
|
argument :name, required: true
|
@@ -122,16 +123,40 @@ module JennCad
|
|
122
123
|
f.puts " end"
|
123
124
|
f.puts "end"
|
124
125
|
end
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
126
|
+
|
127
|
+
lines = File.readlines(executable)
|
128
|
+
magic_line = nil;
|
129
|
+
lines.each_with_index do |l, i|
|
130
|
+
if l.rindex(MAGIC)
|
131
|
+
magic_line = i
|
132
|
+
end
|
133
|
+
end
|
134
|
+
puts "part #{filename} created."
|
135
|
+
if !magic_line
|
136
|
+
puts "In your #{executable} add to class #{executable_class}:"
|
137
|
+
puts " def #{name}"
|
138
|
+
puts " #{classname}.new(config)"
|
139
|
+
puts " end"
|
140
|
+
puts ""
|
141
|
+
puts "For jenncad to insert this line automatically, add this line to your project file before the \"end\"-statement of your class:"
|
142
|
+
puts "##{MAGIC}"
|
143
|
+
else
|
144
|
+
data = "\n"
|
145
|
+
data += " def #{name}\n"
|
146
|
+
data += " #{classname}.new(config)\n"
|
147
|
+
data += " end\n"
|
148
|
+
lines.insert(magic_line, data)
|
149
|
+
f = File.open(executable, "w")
|
150
|
+
f.write(lines.join)
|
151
|
+
f.close
|
152
|
+
end
|
153
|
+
|
129
154
|
|
130
155
|
end
|
131
156
|
|
132
157
|
end
|
133
158
|
|
134
|
-
class NewProject <
|
159
|
+
class NewProject < Dry::CLI::Command
|
135
160
|
include ActiveSupport::Inflector
|
136
161
|
desc "generates a new project"
|
137
162
|
argument :name, required: true
|
@@ -152,9 +177,7 @@ module JennCad
|
|
152
177
|
f.puts " {}"
|
153
178
|
f.puts " end"
|
154
179
|
f.puts ""
|
155
|
-
f.puts "
|
156
|
-
f.puts " cube(10,10,10)"
|
157
|
-
f.puts " end"
|
180
|
+
f.puts " # #{MAGIC}"
|
158
181
|
f.puts "end"
|
159
182
|
f.puts ""
|
160
183
|
f.puts "#{classname}.new.run"
|
@@ -94,7 +94,12 @@ module JennCad::Exporters
|
|
94
94
|
if !v.kind_of?(Array) && !v.kind_of?(TrueClass) && !v.kind_of?(FalseClass) && v == v.to_i
|
95
95
|
v = v.to_i
|
96
96
|
end
|
97
|
-
|
97
|
+
if v.kind_of? String
|
98
|
+
q = "\""
|
99
|
+
else
|
100
|
+
q = ""
|
101
|
+
end
|
102
|
+
res << "#{k}=#{q}#{v}#{q}"
|
98
103
|
end
|
99
104
|
res.join(",").gsub("size=","")
|
100
105
|
else
|
@@ -165,6 +170,8 @@ module JennCad::Exporters
|
|
165
170
|
new_obj(part, :projection, collect_params(part), parse(part.parts))
|
166
171
|
when JennCad::Primitives::Polygon
|
167
172
|
new_obj(part, :polygon, collect_params(part))
|
173
|
+
when JennCad::StlImport
|
174
|
+
new_obj(part, :import, collect_params(part))
|
168
175
|
when JennCad::Part
|
169
176
|
parse(part.part)
|
170
177
|
when nil
|
@@ -192,8 +199,11 @@ module JennCad::Exporters
|
|
192
199
|
end
|
193
200
|
|
194
201
|
def collect_params(part)
|
202
|
+
if part.respond_to? :openscad_params
|
203
|
+
return part.openscad_params
|
204
|
+
end
|
195
205
|
res = {}
|
196
|
-
[:d, :h, :d1, :d2, :size, :fn, :points].each do |var|
|
206
|
+
[:d, :h, :d1, :d2, :size, :fn, :points, :file].each do |var|
|
197
207
|
if part.respond_to? var
|
198
208
|
res[var] = part.send var
|
199
209
|
end
|
@@ -239,7 +249,7 @@ module JennCad::Exporters
|
|
239
249
|
|
240
250
|
# accept aggregation
|
241
251
|
def register_module(part)
|
242
|
-
@modules[part.name] = OpenScadObject.new(:module,part.name, parse(part.part))
|
252
|
+
@modules[part.name] = OpenScadObject.new(:module, part.name, parse(part.part))
|
243
253
|
end
|
244
254
|
|
245
255
|
def handle_import(part)
|
@@ -1,11 +1,15 @@
|
|
1
1
|
module JennCad::Features
|
2
2
|
class Aggregation < Feature
|
3
|
-
attr_accessor :
|
3
|
+
attr_accessor :parts
|
4
4
|
|
5
5
|
def initialize(name=nil, part=nil)
|
6
6
|
super({})
|
7
7
|
@name = name
|
8
|
-
@
|
8
|
+
@parts = [part] # NOTE: single length arrayto make checking children easier
|
9
|
+
end
|
10
|
+
|
11
|
+
def part
|
12
|
+
@parts.first
|
9
13
|
end
|
10
14
|
|
11
15
|
end
|
data/lib/jenncad/features.rb
CHANGED
data/lib/jenncad/part.rb
CHANGED
@@ -2,11 +2,10 @@ module JennCad
|
|
2
2
|
# Part should be inherited from the user when making parts
|
3
3
|
class Part < Thing
|
4
4
|
|
5
|
-
def to_openscad
|
6
|
-
|
7
|
-
a = Aggregation.new(self.class.to_s, self.part) #make_openscad_compatible!(self.part))
|
5
|
+
def to_openscad
|
6
|
+
a = Aggregation.new(self.class.to_s, self.part)
|
8
7
|
a.transformations = @transformations
|
9
|
-
a.color(
|
8
|
+
a.color(:auto)
|
10
9
|
a
|
11
10
|
end
|
12
11
|
|
@@ -2,10 +2,9 @@ module JennCad::Primitives
|
|
2
2
|
class Cube < Primitive
|
3
3
|
extend JennCad::Features::Cuttable
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
end
|
5
|
+
|
6
|
+
def feed_opts(args)
|
7
|
+
# FIXME: this doesn't seem to work
|
9
8
|
if args.kind_of? Array
|
10
9
|
m = {}
|
11
10
|
if args.last.kind_of? Hash
|
@@ -13,7 +12,13 @@ module JennCad::Primitives
|
|
13
12
|
end
|
14
13
|
args = [:x, :y, :z].zip(args.flatten).to_h
|
15
14
|
args.deep_merge!(m)
|
15
|
+
@opts.deep_merge!(args)
|
16
|
+
else
|
17
|
+
@opts.deep_merge!(args)
|
16
18
|
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def initialize(args)
|
17
22
|
@opts = {
|
18
23
|
x: 0,
|
19
24
|
y: 0,
|
@@ -27,10 +32,18 @@ module JennCad::Primitives
|
|
27
32
|
center_y: false,
|
28
33
|
center_x: false,
|
29
34
|
center_z: false,
|
30
|
-
}
|
31
|
-
|
35
|
+
}
|
36
|
+
if args.kind_of? Array
|
37
|
+
args.each do |a|
|
38
|
+
feed_opts(parse_xyz_shortcuts(a))
|
39
|
+
end
|
40
|
+
else
|
41
|
+
feed_opts(parse_xyz_shortcuts(args))
|
42
|
+
end
|
43
|
+
|
32
44
|
|
33
|
-
|
45
|
+
handle_margins
|
46
|
+
super(z: @opts[:z])
|
34
47
|
@h = @z.dup
|
35
48
|
@calc_h = @z.dup
|
36
49
|
end
|
@@ -42,30 +55,34 @@ module JennCad::Primitives
|
|
42
55
|
|
43
56
|
def not_centered
|
44
57
|
@opts[:center] = false
|
58
|
+
self
|
45
59
|
end
|
46
60
|
alias :nc :not_centered
|
47
61
|
|
48
62
|
def cx
|
49
63
|
nc
|
50
64
|
@opts[:center_x] = true
|
65
|
+
self
|
51
66
|
end
|
52
67
|
|
53
68
|
def cy
|
54
69
|
nc
|
55
70
|
@opts[:center_y] = true
|
71
|
+
self
|
56
72
|
end
|
57
73
|
|
58
74
|
def cz
|
59
75
|
nc
|
60
76
|
@opts[:center_z] = true
|
77
|
+
self
|
61
78
|
end
|
62
79
|
|
63
80
|
def centered_axis
|
64
81
|
return [:x, :y] if @opts[:center]
|
65
82
|
a = []
|
66
83
|
a << :x if @opts[:center_x]
|
67
|
-
a << :y if @opts[:
|
68
|
-
a << :z if @opts[:
|
84
|
+
a << :y if @opts[:center_y]
|
85
|
+
a << :z if @opts[:center_z]
|
69
86
|
a
|
70
87
|
end
|
71
88
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module JennCad::Primitives
|
2
2
|
class Cylinder < Primitive
|
3
|
-
attr_accessor :d, :r, :fn
|
3
|
+
attr_accessor :d, :d1, :d2, :r, :fn
|
4
4
|
def initialize(args)
|
5
5
|
if args.kind_of?(Array) && args[0].kind_of?(Hash)
|
6
6
|
args = args.first
|
@@ -43,6 +43,20 @@ module JennCad::Primitives
|
|
43
43
|
super(args)
|
44
44
|
end
|
45
45
|
|
46
|
+
def openscad_params
|
47
|
+
res = {}
|
48
|
+
if @opts[:d1]
|
49
|
+
[:d1, :d2, :h, :fn].each do |n|
|
50
|
+
res[n] = self.send n
|
51
|
+
end
|
52
|
+
else
|
53
|
+
[:d, :h, :fn].each do |n|
|
54
|
+
res[n] = self.send n
|
55
|
+
end
|
56
|
+
end
|
57
|
+
res
|
58
|
+
end
|
59
|
+
|
46
60
|
def handle_fn
|
47
61
|
case @opts[:fn]
|
48
62
|
when nil, 0
|
@@ -70,6 +84,20 @@ module JennCad::Primitives
|
|
70
84
|
@d = @opts[:d].to_f + @opts[:margins][:d].to_f
|
71
85
|
@r = @d / 2.0
|
72
86
|
end
|
87
|
+
|
88
|
+
case @opts[:d1]
|
89
|
+
when 0, nil
|
90
|
+
else
|
91
|
+
@d1 = @opts[:d1].to_f + @opts[:margins][:d].to_f
|
92
|
+
@d2 = @opts[:d2].to_f + @opts[:margins][:d].to_f
|
93
|
+
end
|
94
|
+
|
95
|
+
case @opts[:r1]
|
96
|
+
when 0, nil
|
97
|
+
else
|
98
|
+
@d1 = 2 * @opts[:r1].to_f + @opts[:margins][:d].to_f
|
99
|
+
@d2 = 2 * @opts[:r2].to_f + @opts[:margins][:d].to_f
|
100
|
+
end
|
73
101
|
end
|
74
102
|
|
75
103
|
def h
|
@@ -1,10 +1,10 @@
|
|
1
1
|
module JennCad::Primitives
|
2
|
-
attr_accessor :center_bool, :convexity, :twist, :slices
|
2
|
+
attr_accessor :center_bool, :convexity, :twist, :slices
|
3
3
|
class LinearExtrude < JennCad::Thing
|
4
|
-
def initialize(part, args)
|
4
|
+
def initialize(part, args={})
|
5
5
|
@transformations = []
|
6
6
|
@parts = [part]
|
7
|
-
@
|
7
|
+
@z = args[:h] || args[:height]
|
8
8
|
@center_bool = args[:center]
|
9
9
|
@convexity = args[:convexity]
|
10
10
|
@twist = args[:twist]
|
@@ -12,6 +12,10 @@ module JennCad::Primitives
|
|
12
12
|
@fn = args[:fn]
|
13
13
|
end
|
14
14
|
|
15
|
+
def height
|
16
|
+
@z
|
17
|
+
end
|
18
|
+
|
15
19
|
def openscad_params
|
16
20
|
res = {}
|
17
21
|
[:height, :convexity, :twist, :slices, :fn].each do |n|
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module JennCad::Primitives
|
2
|
-
class RoundedCube <
|
2
|
+
class RoundedCube < Cube
|
3
3
|
attr_accessor :d, :r
|
4
4
|
include JennCad::Features::Cuttable
|
5
5
|
|
@@ -23,6 +23,10 @@ module JennCad::Primitives
|
|
23
23
|
z: nil,
|
24
24
|
r: nil,
|
25
25
|
flat_edges: nil,
|
26
|
+
center: true,
|
27
|
+
center_y: false,
|
28
|
+
center_x: false,
|
29
|
+
center_z: false,
|
26
30
|
margins: {
|
27
31
|
r: 0,
|
28
32
|
d: 0,
|
@@ -41,16 +45,16 @@ module JennCad::Primitives
|
|
41
45
|
# make diameter not bigger than any side
|
42
46
|
@d = [@d, @x, @y].min
|
43
47
|
res = HullObject.new(
|
44
|
-
cylinder(d:@d, h:z+z_margin)
|
45
|
-
cylinder(d:@d).
|
46
|
-
cylinder(d:@d).
|
47
|
-
cylinder(d:@d).
|
48
|
-
)
|
48
|
+
cylinder(d:@d, h:z+z_margin),
|
49
|
+
cylinder(d:@d).move(x: @x - @d, y: 0),
|
50
|
+
cylinder(d:@d).move(x: 0, y: @y - @d),
|
51
|
+
cylinder(d:@d).move(x: @x - @d, y: @y - @d),
|
52
|
+
).moveh(xy: @d)
|
49
53
|
|
50
54
|
res += flat_edge(@opts[:flat_edges])
|
51
55
|
|
52
56
|
res.transformations = @transformations
|
53
|
-
res
|
57
|
+
res.moveh(centered_axis.to_h{|a| [a, -@opts[a]] })
|
54
58
|
end
|
55
59
|
|
56
60
|
def flat_edge(edge)
|
data/lib/jenncad/shortcuts.rb
CHANGED
data/lib/jenncad/thing.rb
CHANGED
@@ -7,6 +7,7 @@ module JennCad
|
|
7
7
|
attr_accessor :calc_x, :calc_y, :calc_z, :calc_h
|
8
8
|
attr_accessor :shape
|
9
9
|
attr_accessor :angle, :fn
|
10
|
+
attr_accessor :anchor
|
10
11
|
|
11
12
|
def initialize(args={})
|
12
13
|
@transformations = []
|
@@ -28,6 +29,41 @@ module JennCad
|
|
28
29
|
@opts[key] = val
|
29
30
|
end
|
30
31
|
|
32
|
+
def set_anchor(args)
|
33
|
+
self.anchor ||= {}
|
34
|
+
args.each do |key, val|
|
35
|
+
self.anchor[key] = val
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def movea(key)
|
40
|
+
a = self.anchor[key]
|
41
|
+
unless a
|
42
|
+
puts "Error: Anchor #{key} not found"
|
43
|
+
puts "Available anchor: #{self.anchor}"
|
44
|
+
return self
|
45
|
+
else
|
46
|
+
self.movei(a)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def movei(args)
|
51
|
+
to = {}
|
52
|
+
[:x, :y, :z].each do |key|
|
53
|
+
if args[key]
|
54
|
+
to[key] = args[key]*-1
|
55
|
+
end
|
56
|
+
end
|
57
|
+
move(to)
|
58
|
+
end
|
59
|
+
|
60
|
+
|
61
|
+
def auto_extrude
|
62
|
+
ret = self.extrude
|
63
|
+
ret.set_option(:auto_extrude, true)
|
64
|
+
ret
|
65
|
+
end
|
66
|
+
|
31
67
|
def rotate(args)
|
32
68
|
@transformations ||= []
|
33
69
|
@transformations << Rotate.new(args)
|
@@ -96,17 +132,43 @@ module JennCad
|
|
96
132
|
[v.x,v.y,v.z]
|
97
133
|
end
|
98
134
|
|
99
|
-
# todo: check if that works
|
100
135
|
def rotate_around(point,args)
|
101
|
-
x,y,z= point
|
136
|
+
x,y,z= point[:x], point[:y], point[:z]
|
102
137
|
self.move(x:-x,y:-y,z:-z).rotate(args).move(x:x,y:y,z:z)
|
103
138
|
end
|
104
139
|
|
140
|
+
def parse_xyz_shortcuts(args)
|
141
|
+
[:x, :y, :z].each do |key|
|
142
|
+
args[key] ||= 0.0
|
143
|
+
end
|
144
|
+
|
145
|
+
if args[:xy]
|
146
|
+
args[:x] += args[:xy]
|
147
|
+
args[:y] += args[:xy]
|
148
|
+
end
|
149
|
+
if args[:xyz]
|
150
|
+
args[:x] += args[:xyz]
|
151
|
+
args[:y] += args[:xyz]
|
152
|
+
args[:z] += args[:xyz]
|
153
|
+
end
|
154
|
+
if args[:xz]
|
155
|
+
args[:x] += args[:xz]
|
156
|
+
args[:z] += args[:xz]
|
157
|
+
end
|
158
|
+
if args[:yz]
|
159
|
+
args[:y] += args[:yz]
|
160
|
+
args[:z] += args[:yz]
|
161
|
+
end
|
162
|
+
return args
|
163
|
+
end
|
164
|
+
|
105
165
|
def move(args)
|
106
166
|
if args.kind_of? Array
|
107
167
|
x,y,z = args
|
108
168
|
return move(x:x, y:y, z:z)
|
109
169
|
end
|
170
|
+
args = parse_xyz_shortcuts(args)
|
171
|
+
|
110
172
|
@transformations ||= []
|
111
173
|
if args[:prepend]
|
112
174
|
@transformations.prepend(Move.new(args))
|
@@ -139,9 +201,9 @@ module JennCad
|
|
139
201
|
x,y,z = args
|
140
202
|
args = {x: x, y: y, z: z}
|
141
203
|
end
|
142
|
-
|
143
|
-
|
144
|
-
|
204
|
+
[:x, :y, :z, :xy, :xyz, :xz, :yz].each do |key|
|
205
|
+
args[key] = args[key] / 2.0 unless args[key] == nil
|
206
|
+
end
|
145
207
|
|
146
208
|
move(args)
|
147
209
|
end
|
@@ -228,8 +290,7 @@ module JennCad
|
|
228
290
|
end
|
229
291
|
res
|
230
292
|
end
|
231
|
-
|
232
|
-
def make_openscad_compatible
|
293
|
+
=begin def make_openscad_compatible
|
233
294
|
make_openscad_compatible!(self)
|
234
295
|
end
|
235
296
|
|
@@ -250,39 +311,111 @@ module JennCad
|
|
250
311
|
end
|
251
312
|
item
|
252
313
|
end
|
314
|
+
=end
|
315
|
+
|
316
|
+
def has_explicit_color?
|
317
|
+
if option(:auto_color) == false
|
318
|
+
return true
|
319
|
+
end
|
320
|
+
return false
|
321
|
+
end
|
322
|
+
|
323
|
+
def only_color?(parts, lvl=0)
|
324
|
+
return true if parts == nil
|
325
|
+
|
326
|
+
parts.each do |part|
|
327
|
+
# puts " " * lvl + "[only_color?] #{part}"
|
328
|
+
if part.has_explicit_color?
|
329
|
+
# puts " " * lvl + "found explicit color here"
|
330
|
+
return false
|
331
|
+
end
|
332
|
+
if !only_color?(part.parts, lvl+1)
|
333
|
+
return false
|
334
|
+
end
|
335
|
+
end
|
336
|
+
true
|
337
|
+
end
|
338
|
+
|
339
|
+
def set_auto_color_for_children(col, parts, lvl=0)
|
340
|
+
return if parts == nil
|
341
|
+
|
342
|
+
parts.each do |part|
|
343
|
+
unless part.has_explicit_color?
|
344
|
+
if only_color?(part.parts, lvl+1)
|
345
|
+
# puts " " * lvl + "children have no explicit color, setting it here"
|
346
|
+
part.set_auto_color(col)
|
347
|
+
else
|
348
|
+
# puts " " * lvl + "[set_auto_color_for_children] #{part}"
|
349
|
+
set_auto_color_for_children(col, part.parts, lvl+1)
|
350
|
+
end
|
351
|
+
else
|
352
|
+
# puts " " * lvl + "[set_auto_color_for_children] this part has a color, ignoring their children"
|
353
|
+
end
|
354
|
+
|
355
|
+
end
|
356
|
+
end
|
357
|
+
|
358
|
+
def set_auto_color(col)
|
359
|
+
set_option :color, col
|
360
|
+
set_option :auto_color, true
|
361
|
+
end
|
253
362
|
|
254
363
|
def color(args=nil)
|
255
|
-
|
256
|
-
when nil
|
364
|
+
if args == nil
|
257
365
|
return option(:color)
|
258
|
-
|
259
|
-
|
366
|
+
end
|
367
|
+
|
368
|
+
if args == :auto
|
369
|
+
ac = auto_color
|
370
|
+
unless ac.nil?
|
371
|
+
#puts "auto color to #{ac}"
|
372
|
+
if only_color?(get_contents)
|
373
|
+
set_option :color, ac
|
374
|
+
set_option :auto_color, true
|
375
|
+
else
|
376
|
+
set_auto_color_for_children(ac, get_contents)
|
377
|
+
end
|
378
|
+
|
379
|
+
end
|
380
|
+
return self
|
381
|
+
end
|
382
|
+
|
383
|
+
c = color_parse(args)
|
384
|
+
unless c.nil?
|
385
|
+
set_option :color, c
|
386
|
+
set_option :auto_color, false
|
387
|
+
end
|
388
|
+
|
389
|
+
self
|
390
|
+
end
|
391
|
+
|
392
|
+
def color_parse(args=nil)
|
393
|
+
case args
|
260
394
|
when :none
|
261
395
|
set_option :no_auto_color, true
|
262
396
|
when :random
|
263
|
-
|
397
|
+
return Color.random
|
264
398
|
when Array
|
265
|
-
|
399
|
+
return Color.parse(args)
|
266
400
|
when /(?<=#)(?<!^)(\h{6}|\h{3})/
|
267
|
-
|
401
|
+
return args
|
268
402
|
when /(?<!^)(\h{6}|\h{3})/
|
269
|
-
|
403
|
+
return "##{args}"
|
270
404
|
when String
|
271
|
-
|
272
|
-
else
|
273
|
-
puts "meow"
|
405
|
+
return args
|
274
406
|
end
|
275
|
-
|
407
|
+
nil
|
276
408
|
end
|
277
409
|
|
278
410
|
def auto_color
|
279
411
|
if option(:color) == nil && !option(:no_auto_color)
|
280
|
-
auto_color!
|
412
|
+
return auto_color!
|
281
413
|
end
|
414
|
+
nil
|
282
415
|
end
|
283
416
|
|
284
417
|
def auto_color!
|
285
|
-
|
418
|
+
color_parse($jenncad_profile.colors.pop)
|
286
419
|
end
|
287
420
|
|
288
421
|
def color_or_fallback
|
@@ -290,12 +423,44 @@ module JennCad
|
|
290
423
|
option(:color)
|
291
424
|
end
|
292
425
|
|
293
|
-
def
|
294
|
-
|
295
|
-
|
296
|
-
|
426
|
+
def get_contents
|
427
|
+
return @parts unless @parts.nil?
|
428
|
+
if self.respond_to? :part
|
429
|
+
return [part]
|
430
|
+
end
|
431
|
+
end
|
432
|
+
|
433
|
+
def calculated_h
|
434
|
+
return @z unless @z.nil? || @z == 0
|
435
|
+
return @h unless @h.nil? || @h == 0
|
436
|
+
return @calc_h unless @calc_h.nil? || @calc_h == 0
|
437
|
+
return @calc_z unless @calc_z.nil? || @calc_z == 0
|
438
|
+
end
|
439
|
+
|
440
|
+
def find_calculated_h(parts)
|
441
|
+
return if parts == nil
|
442
|
+
parts.each do |part|
|
443
|
+
if z = calculated_h
|
444
|
+
return z
|
445
|
+
end
|
446
|
+
get_calculated_h(part.get_contents)
|
447
|
+
end
|
448
|
+
end
|
449
|
+
|
450
|
+
def set_heights_for_auto_extrude(parts, parent=nil)
|
451
|
+
return if parts.nil?
|
452
|
+
parts.each do |part|
|
453
|
+
if part.option(:auto_extrude)
|
454
|
+
part.z = parent.calculated_h
|
297
455
|
end
|
456
|
+
set_heights_for_auto_extrude(part.get_contents, part)
|
298
457
|
end
|
458
|
+
end
|
459
|
+
|
460
|
+
def openscad(file)
|
461
|
+
set_heights_for_auto_extrude(get_contents)
|
462
|
+
|
463
|
+
@parts = get_contents
|
299
464
|
|
300
465
|
JennCad::Exporters::OpenScad.new(self).save(file)
|
301
466
|
end
|
data/lib/jenncad/version.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.alpha7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jennifer Glauche
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-04-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: geo3d
|
@@ -39,7 +39,7 @@ dependencies:
|
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
42
|
+
name: dry-cli
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - ">="
|
@@ -88,6 +88,7 @@ executables:
|
|
88
88
|
extensions: []
|
89
89
|
extra_rdoc_files: []
|
90
90
|
files:
|
91
|
+
- README.md
|
91
92
|
- Rakefile
|
92
93
|
- bin/jenncad
|
93
94
|
- examples/old/cube.rb
|
@@ -114,6 +115,7 @@ files:
|
|
114
115
|
- lib/jenncad/features/cuttable.rb
|
115
116
|
- lib/jenncad/features/feature.rb
|
116
117
|
- lib/jenncad/features/openscad_include.rb
|
118
|
+
- lib/jenncad/features/stl_import.rb
|
117
119
|
- lib/jenncad/part.rb
|
118
120
|
- lib/jenncad/patches/array.rb
|
119
121
|
- lib/jenncad/primitives.rb
|
@@ -151,7 +153,7 @@ homepage: ''
|
|
151
153
|
licenses:
|
152
154
|
- LGPL-3
|
153
155
|
metadata: {}
|
154
|
-
post_install_message:
|
156
|
+
post_install_message:
|
155
157
|
rdoc_options: []
|
156
158
|
require_paths:
|
157
159
|
- lib
|
@@ -166,8 +168,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
166
168
|
- !ruby/object:Gem::Version
|
167
169
|
version: 1.3.1
|
168
170
|
requirements: []
|
169
|
-
rubygems_version: 3.
|
170
|
-
signing_key:
|
171
|
+
rubygems_version: 3.2.3
|
172
|
+
signing_key:
|
171
173
|
specification_version: 4
|
172
174
|
summary: TBD
|
173
175
|
test_files: []
|