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

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.
@@ -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