jenncad 1.0.0.pre.alpha3 → 1.0.0.pre.alpha7

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 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: []