jenncad 1.0.0.pre.alpha19 → 1.0.0.pre.alpha22

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,50 @@
1
+ module JennCad::Primitives
2
+ class Text < Primitive
3
+ attr_accessor :text, :font, :valign, :halign, :size, :spacing, :script, :fn, :direction, :language
4
+
5
+ def initialize(args)
6
+ @text = args[:text]
7
+ @size = args[:size]
8
+ @font = args[:font]
9
+ @valign = args[:valign]
10
+ @halign = args[:halign]
11
+ @spacing = args[:spacing]
12
+ @script = args[:script]
13
+ @direction = parse_dir(args[:dir] || args[:direction])
14
+ case @direction
15
+ when "btt", "ttb"
16
+ @valign ||= :top
17
+ @halign ||= :left
18
+ end
19
+
20
+ @language = args[:language]
21
+ @fn = args[:fn]
22
+
23
+ init(args)
24
+ end
25
+
26
+ def parse_dir(dir)
27
+ case dir.to_s
28
+ when "x", "ltr"
29
+ "ltr"
30
+ when "-x", "xn", "nx", "xi", "rtl"
31
+ "rtl"
32
+ when "y", "btt"
33
+ "btt"
34
+ when "-y", "yn", "ny", "yi", "ttb"
35
+ "ttb"
36
+ else
37
+ nil
38
+ end
39
+ end
40
+
41
+ def openscad_params
42
+ res = {}
43
+ [:text, :font, :valign, :halign, :size, :spacing, :script, :direction, :language, :fn].each do |n|
44
+ res[n] = self.send n
45
+ end
46
+ res
47
+ end
48
+
49
+ end
50
+ end
@@ -1,5 +1,21 @@
1
1
  module JennCad::Primitives
2
2
  class UnionObject < BooleanObject
3
+ def initialize(*parts)
4
+ super(*parts)
5
+
6
+ blacklist = [SubtractObject, IntersectionObject]
7
+
8
+ @parts[1..-1].each do |part|
9
+ blacklist.each do |b|
10
+ if part.kind_of? b
11
+ next
12
+ end
13
+ end
14
+ @csize = part.csize
15
+ # @csize.union(part.csize.clone) if part.csize
16
+ end
17
+
18
+ end
3
19
 
4
20
  end
5
21
  end
@@ -16,6 +16,7 @@ require "jenncad/primitives/intersection_object"
16
16
  require "jenncad/primitives/projection"
17
17
  require "jenncad/primitives/linear_extrude"
18
18
  require "jenncad/primitives/rotate_extrude"
19
+ require "jenncad/primitives/text"
19
20
 
20
21
  module JennCad
21
22
  include Primitives
@@ -17,10 +17,18 @@ module JennCad
17
17
  run_exports
18
18
  end
19
19
 
20
+ def run_export!(part, file)
21
+ part.openscad([output_dir,file].join("/"))
22
+ end
23
+
20
24
  def run_exports
21
25
  outputs.each do |name|
22
26
  part = self.send(name)
23
- part.openscad([output_dir,"#{name}.scad"].join("/"))
27
+ run_export!(part, "#{name}.scad")
28
+ if part.respond_to? :print
29
+ part = self.send(name).print
30
+ run_export!(part, "#{name}_print.scad")
31
+ end
24
32
  end
25
33
  end
26
34
 
@@ -0,0 +1,65 @@
1
+ module CircleIsh
2
+
3
+ def radius
4
+ if @opts[:d]
5
+ @opts[:d].to_d / 2.0
6
+ else
7
+ @opts[:r].to_d
8
+ end
9
+ end
10
+
11
+ def set_anchors_2d
12
+ @anchors = {} # reset anchors
13
+ rad = radius
14
+ # Similar to cube
15
+ set_anchor :left, x: -rad
16
+ set_anchor :right, x: rad
17
+ set_anchor :top, y: rad
18
+ set_anchor :bottom, y: -rad
19
+ end
20
+
21
+ def handle_fn
22
+ case @opts[:fn]
23
+ when nil, 0
24
+ $fn = auto_dn!
25
+ else
26
+ @fn = @opts[:fn]
27
+ end
28
+ end
29
+
30
+ def auto_dn!
31
+ case @d
32
+ when (16..)
33
+ @fn = (@d*4).ceil
34
+ else
35
+ @fn = 64
36
+ end
37
+ end
38
+
39
+ def handle_radius_diameter
40
+ case @opts[:d]
41
+ when 0, nil
42
+ @r = @opts[:r].to_d + @opts[:margins][:r].to_d
43
+ @d = @r * 2.0
44
+ else
45
+ @d = @opts[:d].to_d + @opts[:margins][:d].to_d
46
+ @r = @d / 2.0
47
+ end
48
+
49
+ case @opts[:d1]
50
+ when 0, nil
51
+ else
52
+ @d1 = @opts[:d1].to_d + @opts[:margins][:d].to_d
53
+ @d2 = @opts[:d2].to_d + @opts[:margins][:d].to_d
54
+ end
55
+
56
+ case @opts[:r1]
57
+ when 0, nil
58
+ else
59
+ @d1 = 2 * @opts[:r1].to_d + @opts[:margins][:d].to_d
60
+ @d2 = 2 * @opts[:r2].to_d + @opts[:margins][:d].to_d
61
+ end
62
+ end
63
+
64
+
65
+ end
@@ -0,0 +1,5 @@
1
+ module CubeIsh
2
+ # TBD
3
+
4
+
5
+ end
@@ -0,0 +1,55 @@
1
+ module ZIsh
2
+
3
+ def set_anchors_z
4
+ if @opts[:center_z]
5
+ set_anchor :bottom_face, z: -z/2.0
6
+ set_anchor :top_face, z: z/2.0
7
+ set_anchor :center, x: 0
8
+ else
9
+ set_anchor :bottom_face, z: 0
10
+ set_anchor :top_face, z: z
11
+ set_anchor :center, zh: z
12
+ end
13
+ end
14
+
15
+ def cz
16
+ if self.respond_to? :nc
17
+ nc
18
+ end
19
+ @opts[:center_z] = true
20
+ set_anchors_z
21
+ self
22
+ end
23
+ alias :center_z :cz
24
+
25
+ def flip_axis(dir)
26
+ case dir
27
+ when :bottom
28
+ nil
29
+ when :top
30
+ :z
31
+ when :left, :right
32
+ :x
33
+ when :front, :back
34
+ :y
35
+ end
36
+ end
37
+
38
+ def flip_rotation(dir)
39
+ case dir
40
+ when :bottom
41
+ {}
42
+ when :left
43
+ {y: 270}
44
+ when :top
45
+ {x: 180}
46
+ when :right
47
+ {y: 90}
48
+ when :front
49
+ {x: 90}
50
+ when :back
51
+ {x: 270}
52
+ end
53
+ end
54
+
55
+ end
@@ -0,0 +1,4 @@
1
+ require "jenncad/shared/circle_ish"
2
+ require "jenncad/shared/cube_ish"
3
+ require "jenncad/shared/z_ish"
4
+
@@ -2,6 +2,7 @@ module JennCad
2
2
  def circle(args)
3
3
  Circle.new(args).set_parent(self)
4
4
  end
5
+ alias :ci :circle
5
6
 
6
7
  def square(args)
7
8
  Square.new(args).set_parent(self)
@@ -22,14 +23,17 @@ module JennCad
22
23
  def polygon(args)
23
24
  Polygon.new(args).set_parent(self)
24
25
  end
26
+ alias :pg :polygon
25
27
 
26
28
  def polyhedron(args)
27
29
  Polyhedron.new(args).set_parent(self)
28
30
  end
31
+ alias :phd :polyhedron
29
32
 
30
33
  def slot(*args)
31
34
  Slot.new(args).set_parent(self)
32
35
  end
36
+ alias :sl :slot
33
37
 
34
38
  def cube(*args)
35
39
  Cube.new(args).set_parent(self)
@@ -55,14 +59,23 @@ module JennCad
55
59
  def extrude(args={})
56
60
  LinearExtrude.new(self, args)
57
61
  end
62
+ alias :e :extrude
63
+ alias :ex :extrude
58
64
 
59
65
  def rotate_extrude(args={})
60
66
  RotateExtrude.new(self, args)
61
67
  end
68
+ alias :re :rotate_extrude
69
+ alias :rex :rotate_extrude
62
70
 
63
71
  def to_2d(args={})
64
72
  Projection.new(self, args)
65
73
  end
74
+ alias :as_2d :to_2d
75
+
76
+ def text(txt, args={})
77
+ Text.new(args.merge({text: txt}))
78
+ end
66
79
 
67
80
  def union(*args)
68
81
  UnionObject.new(*args)
data/lib/jenncad/thing.rb CHANGED
@@ -9,17 +9,21 @@ module JennCad
9
9
  attr_accessor :angle, :fn
10
10
  attr_accessor :anchors
11
11
  attr_accessor :parent
12
+ attr_accessor :pos, :csize
13
+ attr_accessor :sits_on
12
14
 
13
15
  def initialize(args={})
14
16
  init(args)
15
17
  end
16
18
 
17
19
  def init(args={})
20
+ @csize = Size.new()
18
21
  @transformations = []
19
22
  # calculated origin; only works for move atm
20
23
  @calc_x = 0
21
24
  @calc_y = 0
22
25
  @calc_z = 0
26
+ @pos = Point.new
23
27
  @calc_h = args[:z] || 0
24
28
  @anchors = {}
25
29
  @parent = args[:parent] || nil
@@ -47,6 +51,10 @@ module JennCad
47
51
  self
48
52
  end
49
53
 
54
+ def dbg
55
+ set_flag(:debug)
56
+ self
57
+ end
50
58
 
51
59
  def cut_to(face, part=nil, args={})
52
60
  an = anchor(face, part)
@@ -145,6 +153,20 @@ module JennCad
145
153
  end
146
154
  alias :sa :set_anchor
147
155
 
156
+ def copy_anchors(thing)
157
+ @anchors = thing.anchors
158
+ end
159
+
160
+ def copy_anchor(name, thing=nil)
161
+ # since it might be confusing to use / use shortcuts for copy_anchor and copy_anchors, let copy_anchor copy all of them when only one parameter is given
162
+ if thing.nil?
163
+ return copy_anchors(name)
164
+ end
165
+ @anchors ||= {}
166
+ @anchors[name] = thing.anchor(name)
167
+ end
168
+ alias :cpa :copy_anchor
169
+
148
170
  def set_anchor_from(name, new_name, args={})
149
171
  unless name.kind_of? Symbol or name.kind_of? String
150
172
  $log.error "set_anchor_from: name must be a string or symbol. Supplied: #{name}"
@@ -196,36 +218,50 @@ module JennCad
196
218
  rt(z:v)
197
219
  end
198
220
 
199
- def flip(direction)
200
- case self
201
- when UnionObject
202
- ref = self.parts.first
203
- rz = self.z.to_d + self.calc_h.to_d
204
- when BooleanObject
205
- ref = self.parts.first
206
- rz = ref.calc_z + ref.calc_h
207
- else
208
- ref = self
209
- rz = self.z + self.calc_h
210
- end
221
+ def flipc(dir, args={})
222
+ flip(dir, args.merge(rel: true, center: true))
223
+ end
224
+
225
+ def flip(dir, args={})
226
+ @sits_on ||= :bottom
211
227
 
212
- case direction
213
- when :x
214
- self.ry(90).mh(x: -rz, z: ref.x)
215
- when :y
216
- self.rx(90).mh(y: rz, z: ref.y)
228
+ ro = flip_rotation(dir)
229
+ flip_rotation(@sits_on).each do |key, val|
230
+ ro[key] ||= 0
231
+ ro[key] -= val
232
+ end
233
+ unless ro == {}
234
+ self.moveai(:center).rotate(ro)
217
235
  end
218
- end
219
236
 
220
- def flip_x
221
- flip(:x)
222
- end
223
- alias :fx :flip_x
237
+ @opts ||= {}
238
+
239
+ if args[:center]
240
+ if ro == {} # if we didn't move earlier, let's move it now
241
+ self.moveai(:center)
242
+ end
243
+ @opts[:center_z] = true
244
+ set_anchors_z if self.respond_to? :set_anchors_z
245
+ else
246
+ # TODO: fix anchors
247
+ if debug?
248
+ $log.info "flip_axis(#{dir}): #{flip_axis(dir)} csize: #{@csize.size}"
249
+ end
250
+
251
+ case flip_axis(dir)
252
+ when :x
253
+ self.move(zh: @csize.x)
254
+ when :y
255
+ self.move(zh: @csize.y)
256
+ when :z
257
+ self.move(zh: @csize.z)
258
+ end
259
+ @opts[:center_z] = false
260
+ end
261
+ @sits_on = dir
224
262
 
225
- def flip_y
226
- flip(:y)
263
+ self
227
264
  end
228
- alias :fy :flip_y
229
265
 
230
266
  def radians(a)
231
267
  a.to_d/180.0*PI
@@ -250,6 +286,7 @@ module JennCad
250
286
  self.move(x:-x,y:-y,z:-z).rotate(args).move(x:x,y:y,z:z)
251
287
  end
252
288
 
289
+ # Deprecated, moved to Point
253
290
  def parse_xyz_shortcuts(args)
254
291
  unless args.kind_of? Hash
255
292
  $log.warn "parse_xyz_shortcuts called for type #{args.class} #{args.inspect}"
@@ -315,34 +352,44 @@ module JennCad
315
352
  x,y,z = args
316
353
  return move(x:x, y:y, z:z)
317
354
  end
318
- args = parse_xyz_shortcuts(args)
319
355
 
320
- if args[:x].to_d == 0.0 && args[:y].to_d == 0.0 && args[:z].to_d == 0.0
356
+ chain = if args[:chain]
357
+ args[:chain]
358
+ else
359
+ $jenncad_profile.chain_moves
360
+ end
361
+
362
+ point = Point.new(args)
363
+
364
+ if point.zero?
321
365
  return self
322
366
  end
367
+ pre = args[:prepend]
368
+ args = point.to_h
323
369
 
324
370
  @transformations ||= []
325
- if args[:prepend]
326
- @transformations.prepend(Move.new(args))
327
- else
328
- lt = @transformations.last
329
-
330
- chain = if args[:chain]
331
- args[:chain]
371
+ if pre
372
+ lt = @transformations.first
373
+ if lt && lt.class == Move && chain == false
374
+ $log.debug "#{self} at move(prepend): Adding to first move #{lt.inspect} , args: #{args}" if self.debug?
375
+ lt.pos.add(point)
332
376
  else
333
- $jenncad_profile.chain_moves
377
+ @transformations.prepend(Move.new(pos: point))
334
378
  end
379
+ else
380
+ lt = @transformations.last
335
381
 
336
382
  if lt && lt.class == Move && chain == false
337
383
  $log.debug "#{self} at move: Adding to previous move #{lt.inspect} , args: #{args}" if self.debug?
338
- lt.x += args[:x].to_d
339
- lt.y += args[:y].to_d
340
- lt.z += args[:z].to_d
384
+ lt.pos.add(point) # TODO: figure out why this doesn't work on export
341
385
  else
342
386
  $log.debug "#{self} at move: Adding move of #{args} to transformations" if self.debug?
343
- @transformations << Move.new(args)
387
+ @transformations << Move.new(pos: point)
344
388
  end
345
389
  end
390
+ @pos ||= Point.new
391
+ @pos.add(point)
392
+ # NOTE: this needs more migration so everythign runs over point
346
393
  @calc_x += args[:x].to_d
347
394
  @calc_y += args[:y].to_d
348
395
  @calc_z += args[:z].to_d
@@ -363,6 +410,33 @@ module JennCad
363
410
  move(z:v)
364
411
  end
365
412
 
413
+ # Perform something at an anchor location block
414
+ def at(keys, thing=nil, args={}, &block)
415
+ unless keys.kind_of? Array
416
+ keys = [keys]
417
+ end
418
+
419
+ part = self
420
+ keys.each do |key|
421
+ if key.kind_of? Hash
422
+ an = key
423
+ else
424
+ thing ||= self
425
+ an = anchor(key, thing, args)
426
+ end
427
+ unless an
428
+ $log.error "at on #{thing.class} could not find anchor #{key}"
429
+ an = {} # this will move by 0,0 and still display the block
430
+ end
431
+ part.movei(an)
432
+ bl = block.yield
433
+ unless bl == nil
434
+ part = bl.move(an)
435
+ end
436
+ end
437
+ part
438
+ end
439
+
366
440
  # move to anchor
367
441
  def movea(key, thing=nil, args={})
368
442
  if thing.kind_of? Hash # if you leave out thing, args may be interpreted as thing
@@ -407,11 +481,14 @@ module JennCad
407
481
  x,y,z = args
408
482
  args = {x: x, y: y, z: z}
409
483
  end
410
- [:x, :y, :z, :xy, :xyz, :xz, :yz].each do |key|
411
- args[key] = args[key] / 2.0 unless args[key] == nil
484
+ to = {}
485
+ args.each do |key, val|
486
+ to[key] = val.to_d / 2.0 if val.kind_of? Numeric
412
487
  end
488
+ to[:chain] = args[:chain]
489
+ to[:prepend] = args[:prepend]
413
490
 
414
- move(args)
491
+ move(to)
415
492
  end
416
493
  alias :mh :moveh
417
494
 
@@ -429,11 +506,9 @@ module JennCad
429
506
 
430
507
  def movei(args={})
431
508
  to = {}
432
- [:x, :y, :z, :xy, :xz, :yz, :xyz].each do |key|
433
- if args[key]
434
- to[key] = args[key]*-1
435
- end
436
- end
509
+ args.each do |key, val|
510
+ to[key] = val.to_d * -1 if val.kind_of? Numeric
511
+ end
437
512
  to[:chain] = args[:chain]
438
513
  move(to)
439
514
  end
@@ -1,7 +1,13 @@
1
1
  module JennCad
2
+ attr_accessor :pos
2
3
  class Move < Transformation
3
4
  def initialize(args)
4
- super(args)
5
+ pos = args[:pos]
6
+ super(args.merge(pos: pos))
7
+ end
8
+
9
+ def coordinates
10
+ @pos.to_a
5
11
  end
6
12
  end
7
13
  end
@@ -3,5 +3,9 @@ module JennCad
3
3
  def initialize(args)
4
4
  super(args)
5
5
  end
6
+
7
+ def coordinates
8
+ [@x, @y, @z]
9
+ end
6
10
  end
7
11
  end
@@ -2,13 +2,14 @@ module JennCad
2
2
  class Transformation
3
3
  attr_accessor :x,:y,:z, :coordinates
4
4
  def initialize(args)
5
+ @pos = args[:pos]
5
6
  @x = args[:x]
6
7
  @y = args[:y]
7
8
  @z = args[:z]
8
9
  end
9
10
 
10
11
  def coordinates
11
- [@x,@y,@z]
12
+ @pos.to_a
12
13
  end
13
14
  end
14
15
  end
@@ -1,3 +1,3 @@
1
1
  module JennCad
2
- VERSION = "1.0.0-alpha19"
2
+ VERSION = "1.0.0-alpha22"
3
3
  end
data/lib/jenncad.rb CHANGED
@@ -1,3 +1,4 @@
1
+ require "pp"
1
2
  require "logger"
2
3
  $log = Logger.new(STDOUT)
3
4
 
@@ -18,11 +19,13 @@ JennCad::ProfileLoader.new
18
19
 
19
20
 
20
21
  require "jenncad/patches/array"
22
+ require "jenncad/position"
21
23
  require "jenncad/thing"
22
24
  require "jenncad/part"
23
25
  require "jenncad/project"
24
26
  require "jenncad/commands"
25
27
 
28
+ require "jenncad/shared"
26
29
  require "jenncad/features"
27
30
  require "jenncad/primitives"
28
31
 
data/todo.txt CHANGED
@@ -24,14 +24,38 @@ Features wanted
24
24
  - but also, when you have a part that can be mounted in any top/bottom direction, you always end up having the bolts facing the wrong direction..
25
25
  - Bolts should be able to also make thread inserts
26
26
 
27
+ - Bolts / Nuts by default should be able to use as mixin, i.e.
28
+ cylinder(Nut::M3)
29
+ slot(Nut::M5, x: 10)
30
+
31
+ possbibly M* like
32
+ cylinder(M4)
33
+ or
34
+ cylinder(M4, h: 25)
35
+
36
+ Possibly via symbols
37
+ cylinder(:m4, h: 30)
38
+ cylinder(:m4, :nut)
39
+
40
+ slot(:m5, :nut, x: 10)
41
+
42
+
27
43
  8.5.22:
28
44
  - need an easy way to switch between faces on an object to work efficiently in a 2.5D way
29
45
  i.e. I worked on a part stacking a few things, added a cube along and now wanted to use inner_anchors for the y face for screws. it was easier to make anchors manually for the prototype
46
+ [#at functionality is half-way there; would be great to have this for rotation as well]
30
47
 
31
48
 
49
+ 23.5.22:
50
+ - get slice of circle (input angle, output angle)
51
+ - skip stl build for part
52
+ - at doesn't work well if you need to mirror a part
53
+ -> anchors need to be able to do flipping, possibly rotation
32
54
 
33
55
 
34
56
 
57
+ 24.5.22
58
+ - multithreading output building
35
59
 
36
60
  other awful things
37
61
  ===================
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.alpha19
4
+ version: 1.0.0.pre.alpha22
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jennifer Glauche
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-05-16 00:00:00.000000000 Z
11
+ date: 2022-05-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: geo3d
@@ -128,6 +128,7 @@ files:
128
128
  - lib/jenncad/features/stl_import.rb
129
129
  - lib/jenncad/part.rb
130
130
  - lib/jenncad/patches/array.rb
131
+ - lib/jenncad/position.rb
131
132
  - lib/jenncad/primitives.rb
132
133
  - lib/jenncad/primitives/boolean_object.rb
133
134
  - lib/jenncad/primitives/circle.rb
@@ -146,10 +147,15 @@ files:
146
147
  - lib/jenncad/primitives/sphere.rb
147
148
  - lib/jenncad/primitives/square.rb
148
149
  - lib/jenncad/primitives/subtract_object.rb
150
+ - lib/jenncad/primitives/text.rb
149
151
  - lib/jenncad/primitives/union_object.rb
150
152
  - lib/jenncad/profile_loader.rb
151
153
  - lib/jenncad/project.rb
152
154
  - lib/jenncad/register.rb
155
+ - lib/jenncad/shared.rb
156
+ - lib/jenncad/shared/circle_ish.rb
157
+ - lib/jenncad/shared/cube_ish.rb
158
+ - lib/jenncad/shared/z_ish.rb
153
159
  - lib/jenncad/shortcuts.rb
154
160
  - lib/jenncad/thing.rb
155
161
  - lib/jenncad/transformation/color.rb