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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b3b2667c6121606bece58cc0edbb2d7c0e0f2454dc175b62c3749209c1eef266
4
- data.tar.gz: d8dbc84a707b0767374830df107ebcb098b89591664f0f7062468404b0c512e2
3
+ metadata.gz: 59b41052c4c676ae59a808744715a5e10b1c1086350d4c7769b87d054f51d171
4
+ data.tar.gz: a620928785ad237699d0afff433912a8b5c5f6d765492d4d1f72d4d4d83fb962
5
5
  SHA512:
6
- metadata.gz: e512b91a4c6355cfd1b516bc52e434b1670e5aae02b39d75581e423a6242a90b11257a4c4902e30db74de0d4c1693aa7608829393df45806ecf56fc3e409bce9
7
- data.tar.gz: 26fad5ebe17ad65610283315c2c33d9d7842717b78ad8560029038238b18c88aa351667a395f24ef134cf3f9fce298fcb1528ca459c7aeebfe618d71a5186233
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
- Hanami::CLI.new(JennCad::Commands).call
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 "hanami-cli"
25
+ gem.add_runtime_dependency "dry-cli"
26
26
  gem.add_runtime_dependency "activesupport"
27
27
  gem.add_runtime_dependency "observr"
28
28
  end
@@ -1,8 +1,9 @@
1
1
  module JennCad
2
2
  module Commands
3
- extend Hanami::CLI::Registry
3
+ extend Dry::CLI::Registry
4
+ MAGIC = "jenncad-append-project-magic"
4
5
 
5
- class Run < Hanami::CLI::Command
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 < Hanami::CLI::Command
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
- puts "part #{filename} created. In your #{executable} add to class #{executable_class}:"
126
- puts " def #{name}"
127
- puts " #{classname}.new(config)"
128
- puts " end"
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 < Hanami::CLI::Command
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 " def #{name}"
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
- res << "#{k}=#{v}"
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 :part
3
+ attr_accessor :parts
4
4
 
5
5
  def initialize(name=nil, part=nil)
6
6
  super({})
7
7
  @name = name
8
- @part = part
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
@@ -0,0 +1,10 @@
1
+ module JennCad::Features
2
+ class StlImport < Feature
3
+ attr_accessor :file, :args
4
+
5
+ def initialize(file, args={})
6
+ @file = file
7
+ @args = args
8
+ end
9
+ end
10
+ end
@@ -3,6 +3,8 @@ require "jenncad/features/aggregation"
3
3
  require "jenncad/features/cuttable"
4
4
  require "jenncad/features/openscad_include"
5
5
  require "jenncad/features/climb"
6
+ require "jenncad/features/stl_import"
7
+
6
8
 
7
9
  module JennCad
8
10
  include Features
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 #make_openscad_compatible
6
- auto_color
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(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
- def initialize(args)
6
- if args.kind_of?(Array) && args[0].kind_of?(Hash)
7
- args = args.first
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
- }.deep_merge!(args)
31
- handle_margins
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
- super(args)
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[:center_x]
68
- a << :z if @opts[:center_x]
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, :height
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
- @height = args[:h] || args[:height]
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
- attr_accessor :convexity
2
+ attr_accessor :cut, :convexity
3
3
  class RotateExtrude < JennCad::Thing
4
4
  def initialize(part, args)
5
5
  @transformations = []
@@ -1,5 +1,5 @@
1
1
  module JennCad::Primitives
2
- class RoundedCube < Primitive
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).moveh(x: -@x + @d, y: @y - @d),
45
- cylinder(d:@d).moveh(x: @x - @d, y: @y - @d),
46
- cylinder(d:@d).moveh(x: -@x + @d, y: -@y + @d),
47
- cylinder(d:@d).moveh(x: @x - @d, y: -@y + @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)
@@ -55,6 +55,7 @@ module JennCad::Primitives
55
55
  part.opts[:margins] ||= {}
56
56
  if part.referenced_z && part.z != 0.0
57
57
  case part
58
+ when JennCad::Circle
58
59
  when JennCad::BooleanObject
59
60
  when JennCad::Aggregation
60
61
  else
@@ -38,7 +38,11 @@ module JennCad
38
38
  OpenScadImport.new(import, name, args)
39
39
  end
40
40
 
41
- def extrude(args)
41
+ def stl(file, args={})
42
+ StlImport.new(file, args)
43
+ end
44
+
45
+ def extrude(args={})
42
46
  LinearExtrude.new(self, args)
43
47
  end
44
48
 
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.x, point.y, point.z
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
- args[:x] = args[:x] / 2.0 unless args[:x] == nil
143
- args[:y] = args[:y] / 2.0 unless args[:y] == nil
144
- args[:z] = args[:z] / 2.0 unless args[:z] == nil
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
- case args
256
- when nil
364
+ if args == nil
257
365
  return option(:color)
258
- when :auto
259
- return auto_color!
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
- set_option :color, Color.random
397
+ return Color.random
264
398
  when Array
265
- set_option :color, Color.parse(args)
399
+ return Color.parse(args)
266
400
  when /(?<=#)(?<!^)(\h{6}|\h{3})/
267
- set_option :color, args
401
+ return args
268
402
  when /(?<!^)(\h{6}|\h{3})/
269
- set_option :color, "##{args}"
403
+ return "##{args}"
270
404
  when String
271
- set_option :color, args
272
- else
273
- puts "meow"
405
+ return args
274
406
  end
275
- self
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
- color($jenncad_profile.colors.pop)
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 openscad(file)
294
- if @parts == nil
295
- if self.respond_to? :part
296
- @parts = [part]
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
@@ -1,4 +1,4 @@
1
1
  module JennCad
2
- VERSION = "1.0.0-alpha3"
2
+ VERSION = "1.0.0-alpha7"
3
3
  end
4
4
 
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.alpha3
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: 2019-06-30 00:00:00.000000000 Z
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: hanami-cli
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.0.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: []