jenncad 1.0.0.pre.alpha9 → 1.0.0.pre.alpha12

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: 93ed5b4cc8c786d306d9fbaa7c0518a607b20c76f08538a0882584ec34955ac4
4
- data.tar.gz: 5394a9131feb628a3d8f4a1d099ce75b104d0f0674c4dbb9d57db19fc555486a
3
+ metadata.gz: ceeccb1511db4a12b24c38116c2daa1835f9a64f3c62fe8446feea6712c9f200
4
+ data.tar.gz: 5b25c737ac0ba61039f7a54d8810a6fd94f2057ca2c482027683105adc767e54
5
5
  SHA512:
6
- metadata.gz: 29deaf817dfce550a7a3038454ddbca39c520ae1964526f7f7ebcf06edca9dbe056ec13d1f84e4390d3dbe0f043324f48c220e8bcb5a38e201b47853603bcca2
7
- data.tar.gz: c4e3a0e515ad6586fbc9919a6f0608375bf4d2babf21b8de202b308227050fae25e3db2d44ca0f4271c67854d9f57508aa5dbf04c576d562b6515ed9da6419d4
6
+ metadata.gz: e509d98347b1a96093fb62ccea12c3e71733f3af4e946694286783e54958245b99373c9721b338bc4da17ddac531a7b215b8394364b4af31aa82c3be8a183cc0
7
+ data.tar.gz: 14ecaa2c0698e5fad95d311f373f2399f98eaa5b1e0220dce807053ce7ea0b505f879dce042006232cac8b6d25dd6e9c08eb1a713f78a09aba9c47c1e9bbdf08
data/LICENSE ADDED
@@ -0,0 +1,165 @@
1
+ GNU LESSER GENERAL PUBLIC LICENSE
2
+ Version 3, 29 June 2007
3
+
4
+ Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
5
+ Everyone is permitted to copy and distribute verbatim copies
6
+ of this license document, but changing it is not allowed.
7
+
8
+
9
+ This version of the GNU Lesser General Public License incorporates
10
+ the terms and conditions of version 3 of the GNU General Public
11
+ License, supplemented by the additional permissions listed below.
12
+
13
+ 0. Additional Definitions.
14
+
15
+ As used herein, "this License" refers to version 3 of the GNU Lesser
16
+ General Public License, and the "GNU GPL" refers to version 3 of the GNU
17
+ General Public License.
18
+
19
+ "The Library" refers to a covered work governed by this License,
20
+ other than an Application or a Combined Work as defined below.
21
+
22
+ An "Application" is any work that makes use of an interface provided
23
+ by the Library, but which is not otherwise based on the Library.
24
+ Defining a subclass of a class defined by the Library is deemed a mode
25
+ of using an interface provided by the Library.
26
+
27
+ A "Combined Work" is a work produced by combining or linking an
28
+ Application with the Library. The particular version of the Library
29
+ with which the Combined Work was made is also called the "Linked
30
+ Version".
31
+
32
+ The "Minimal Corresponding Source" for a Combined Work means the
33
+ Corresponding Source for the Combined Work, excluding any source code
34
+ for portions of the Combined Work that, considered in isolation, are
35
+ based on the Application, and not on the Linked Version.
36
+
37
+ The "Corresponding Application Code" for a Combined Work means the
38
+ object code and/or source code for the Application, including any data
39
+ and utility programs needed for reproducing the Combined Work from the
40
+ Application, but excluding the System Libraries of the Combined Work.
41
+
42
+ 1. Exception to Section 3 of the GNU GPL.
43
+
44
+ You may convey a covered work under sections 3 and 4 of this License
45
+ without being bound by section 3 of the GNU GPL.
46
+
47
+ 2. Conveying Modified Versions.
48
+
49
+ If you modify a copy of the Library, and, in your modifications, a
50
+ facility refers to a function or data to be supplied by an Application
51
+ that uses the facility (other than as an argument passed when the
52
+ facility is invoked), then you may convey a copy of the modified
53
+ version:
54
+
55
+ a) under this License, provided that you make a good faith effort to
56
+ ensure that, in the event an Application does not supply the
57
+ function or data, the facility still operates, and performs
58
+ whatever part of its purpose remains meaningful, or
59
+
60
+ b) under the GNU GPL, with none of the additional permissions of
61
+ this License applicable to that copy.
62
+
63
+ 3. Object Code Incorporating Material from Library Header Files.
64
+
65
+ The object code form of an Application may incorporate material from
66
+ a header file that is part of the Library. You may convey such object
67
+ code under terms of your choice, provided that, if the incorporated
68
+ material is not limited to numerical parameters, data structure
69
+ layouts and accessors, or small macros, inline functions and templates
70
+ (ten or fewer lines in length), you do both of the following:
71
+
72
+ a) Give prominent notice with each copy of the object code that the
73
+ Library is used in it and that the Library and its use are
74
+ covered by this License.
75
+
76
+ b) Accompany the object code with a copy of the GNU GPL and this license
77
+ document.
78
+
79
+ 4. Combined Works.
80
+
81
+ You may convey a Combined Work under terms of your choice that,
82
+ taken together, effectively do not restrict modification of the
83
+ portions of the Library contained in the Combined Work and reverse
84
+ engineering for debugging such modifications, if you also do each of
85
+ the following:
86
+
87
+ a) Give prominent notice with each copy of the Combined Work that
88
+ the Library is used in it and that the Library and its use are
89
+ covered by this License.
90
+
91
+ b) Accompany the Combined Work with a copy of the GNU GPL and this license
92
+ document.
93
+
94
+ c) For a Combined Work that displays copyright notices during
95
+ execution, include the copyright notice for the Library among
96
+ these notices, as well as a reference directing the user to the
97
+ copies of the GNU GPL and this license document.
98
+
99
+ d) Do one of the following:
100
+
101
+ 0) Convey the Minimal Corresponding Source under the terms of this
102
+ License, and the Corresponding Application Code in a form
103
+ suitable for, and under terms that permit, the user to
104
+ recombine or relink the Application with a modified version of
105
+ the Linked Version to produce a modified Combined Work, in the
106
+ manner specified by section 6 of the GNU GPL for conveying
107
+ Corresponding Source.
108
+
109
+ 1) Use a suitable shared library mechanism for linking with the
110
+ Library. A suitable mechanism is one that (a) uses at run time
111
+ a copy of the Library already present on the user's computer
112
+ system, and (b) will operate properly with a modified version
113
+ of the Library that is interface-compatible with the Linked
114
+ Version.
115
+
116
+ e) Provide Installation Information, but only if you would otherwise
117
+ be required to provide such information under section 6 of the
118
+ GNU GPL, and only to the extent that such information is
119
+ necessary to install and execute a modified version of the
120
+ Combined Work produced by recombining or relinking the
121
+ Application with a modified version of the Linked Version. (If
122
+ you use option 4d0, the Installation Information must accompany
123
+ the Minimal Corresponding Source and Corresponding Application
124
+ Code. If you use option 4d1, you must provide the Installation
125
+ Information in the manner specified by section 6 of the GNU GPL
126
+ for conveying Corresponding Source.)
127
+
128
+ 5. Combined Libraries.
129
+
130
+ You may place library facilities that are a work based on the
131
+ Library side by side in a single library together with other library
132
+ facilities that are not Applications and are not covered by this
133
+ License, and convey such a combined library under terms of your
134
+ choice, if you do both of the following:
135
+
136
+ a) Accompany the combined library with a copy of the same work based
137
+ on the Library, uncombined with any other library facilities,
138
+ conveyed under the terms of this License.
139
+
140
+ b) Give prominent notice with the combined library that part of it
141
+ is a work based on the Library, and explaining where to find the
142
+ accompanying uncombined form of the same work.
143
+
144
+ 6. Revised Versions of the GNU Lesser General Public License.
145
+
146
+ The Free Software Foundation may publish revised and/or new versions
147
+ of the GNU Lesser General Public License from time to time. Such new
148
+ versions will be similar in spirit to the present version, but may
149
+ differ in detail to address new problems or concerns.
150
+
151
+ Each version is given a distinguishing version number. If the
152
+ Library as you received it specifies that a certain numbered version
153
+ of the GNU Lesser General Public License "or any later version"
154
+ applies to it, you have the option of following the terms and
155
+ conditions either of that published version or of any later version
156
+ published by the Free Software Foundation. If the Library as you
157
+ received it does not specify a version number of the GNU Lesser
158
+ General Public License, you may choose any version of the GNU Lesser
159
+ General Public License ever published by the Free Software Foundation.
160
+
161
+ If the Library as you received it specifies that a proxy can decide
162
+ whether future versions of the GNU Lesser General Public License shall
163
+ apply, that proxy's public statement of acceptance of any version is
164
+ permanent authorization for you to choose that version for the
165
+ Library.
data/examples/README ADDED
@@ -0,0 +1,4 @@
1
+ Find the examples at:
2
+
3
+ https://github.com/jglauche/jenncad-examples
4
+
data/jenncad.gemspec CHANGED
@@ -25,4 +25,5 @@ Gem::Specification.new do |gem|
25
25
  gem.add_runtime_dependency "dry-cli"
26
26
  gem.add_runtime_dependency "activesupport"
27
27
  gem.add_runtime_dependency "observr"
28
+ gem.add_runtime_dependency "logger"
28
29
  end
@@ -5,7 +5,7 @@ module JennCad
5
5
  MAGIC = "jenncad-append-project-magic"
6
6
 
7
7
  class Run < Dry::CLI::Command
8
- argument :name, required: false
8
+ argument :name, required: false, desc: "project file, defaults to dirname.rb by default"
9
9
 
10
10
  def guess_executable(dir=Dir.pwd)
11
11
  dir.split("/").last.to_s + ".rb"
@@ -42,16 +42,23 @@ module JennCad
42
42
  end
43
43
  end
44
44
 
45
- def build
46
- admesh_installed = system("admesh --version > /dev/null")
47
- unless admesh_installed
48
- puts "Warning: cannot find admesh, stl export will be in ASCII"
45
+ end
46
+
47
+ class Build < Run
48
+ option :binary, type: :boolean, default: false, desc: "run through admesh to create a binary stl"
49
+
50
+ def build(options)
51
+ if options[:binary]
52
+ admesh_installed = system("admesh --version > /dev/null")
53
+ unless admesh_installed
54
+ puts "Warning: cannot find admesh, stl export will be in ASCII"
55
+ end
49
56
  end
50
57
 
51
58
  Dir.glob("output/**/*.scad").each do |file|
52
59
  stl = file.gsub(".scad",".stl")
53
60
  build_stl(file, stl)
54
- convert_to_binary(stl) if admesh_installed
61
+ convert_to_binary(stl) if options[:binary] && admesh_installed
55
62
  end
56
63
  end
57
64
 
@@ -64,16 +71,15 @@ module JennCad
64
71
  system("admesh #{stl} -b #{stl}")
65
72
  end
66
73
 
67
- end
68
74
 
69
- class Build < Run
70
- def call(name: nil, **)
75
+ def call(options)
76
+ name = options[:name]
71
77
  unless name
72
78
  name = guess_executable
73
79
  end
74
80
  if check_executable(name)
75
81
  execute(name)
76
- build
82
+ build(options)
77
83
  end
78
84
  end
79
85
  end
@@ -1,8 +1,10 @@
1
1
  module JennCad::Exporters
2
2
  class OpenScadObject
3
- def initialize(cmd, args, children=[])
3
+ def initialize(cmd, args, children=[], modifier=nil)
4
4
  @command = cmd
5
5
  @args = args
6
+ @modifier = modifier || ""
7
+
6
8
  case children
7
9
  when Array
8
10
  @children = children
@@ -43,11 +45,11 @@ module JennCad::Exporters
43
45
  def handle_command(i=1)
44
46
  case @children.size
45
47
  when 0
46
- "#{@command}(#{handle_args});"
48
+ "#{@modifier}#{@command}(#{handle_args});"
47
49
  when 1
48
- "#{@command}(#{handle_args})#{@children.first.handle_command(i+1)}"
50
+ "#{@modifier}#{@command}(#{handle_args})#{@children.first.handle_command(i+1)}"
49
51
  when (1..)
50
- res = "#{@command}(#{handle_args}){"
52
+ res = "#{@modifier}#{@command}(#{handle_args}){"
51
53
  res += nl
52
54
  inner = @children.map do |c|
53
55
  next if c == nil
@@ -185,7 +187,8 @@ module JennCad::Exporters
185
187
  def new_obj(part, cmd, args=nil, children=[])
186
188
  transform(part) do
187
189
  apply_color(part) do
188
- OpenScadObject.new(cmd, args, children)
190
+ modifier = part.openscad_modifier || nil
191
+ OpenScadObject.new(cmd, args, children, modifier)
189
192
  end
190
193
  end
191
194
  end
@@ -4,9 +4,12 @@ module JennCad::Features
4
4
 
5
5
  def initialize(name=nil, part=nil)
6
6
  super({})
7
- @name = name
7
+ @name = name.gsub(".","_")
8
8
  @parts = [part] # NOTE: single length arrayto make checking children easier
9
- @z = part.z
9
+ end
10
+
11
+ def z
12
+ part.z
10
13
  end
11
14
 
12
15
  def part
@@ -7,6 +7,7 @@ module JennCad::Primitives
7
7
  else
8
8
  @parts = parts
9
9
  end
10
+ @parent = @parts.first.parent
10
11
  after_add
11
12
  end
12
13
 
@@ -28,10 +29,17 @@ module JennCad::Primitives
28
29
  def after_add
29
30
  @parts.flatten!
30
31
  @parts.compact!
32
+ inherit_debug
31
33
  inherit_z
32
34
  inherit_zref
33
35
  end
34
36
 
37
+ def inherit_debug
38
+ if @parts.map{|l| l.option(:debug)}.include? true
39
+ set_option(:debug, true)
40
+ end
41
+ end
42
+
35
43
  def inherit_z
36
44
  heights = @parts.map{|l| l.calc_z.to_f}.uniq
37
45
  if heights.size > 1
@@ -75,6 +83,8 @@ module JennCad::Primitives
75
83
  when Array
76
84
  res << obj.map{|l| only_additives_of(l)}
77
85
  when SubtractObject
86
+ # include the thing that something was subtracted from to get the Z height if that is behind another layer of SubtractObject
87
+ res << only_additives_of(obj.parts.first)
78
88
  when IntersectionObject
79
89
  else
80
90
  res << obj
@@ -2,6 +2,7 @@ module JennCad::Primitives
2
2
  class Cube < Primitive
3
3
  extend JennCad::Features::Cuttable
4
4
 
5
+ attr_accessor :corners, :sides
5
6
 
6
7
  def feed_opts(args)
7
8
  # FIXME: this doesn't seem to work
@@ -46,8 +47,102 @@ module JennCad::Primitives
46
47
  super(z: @opts[:z])
47
48
  @h = @z.dup
48
49
  @calc_h = @z.dup
50
+
51
+
52
+ set_anchors
53
+ end
54
+
55
+ def set_anchors
56
+ @anchors = {} # this resets anchors
57
+
58
+ if @opts[:center] || @opts[:center_x]
59
+ left = -@opts[:x] / 2.0
60
+ right = @opts[:x] / 2.0
61
+ mid_x = 0
62
+ else
63
+ left = 0
64
+ right = @opts[:x]
65
+ mid_x = @opts[:x] / 2.0
66
+ end
67
+ if @opts[:center] || @opts[:center_y]
68
+ bottom = -@opts[:y] / 2.0
69
+ top = @opts[:y] / 2.0
70
+ mid_y = 0
71
+ else
72
+ bottom = 0
73
+ top = @opts[:y]
74
+ mid_y = @opts[:y] / 2.0
75
+ end
76
+
77
+ set_anchor :left, x: left, y: mid_y
78
+ set_anchor :right, x: right, y: mid_y
79
+ set_anchor :top, x: mid_x, y: top
80
+ set_anchor :bottom, x: mid_x, y: bottom
81
+ set_anchor :top_left, x: left, y: top
82
+ set_anchor :top_right, x: right, y: top
83
+ set_anchor :bottom_left, x: left, y: bottom
84
+ set_anchor :bottom_right, x: right, y: bottom
85
+
86
+ # we need to re-do the inner ones, if they were defined
87
+ if @inner_anchor_defs && @inner_anchor_defs.size > 0
88
+ @inner_anchor_defs.each do |anch|
89
+ inner_anchors(anch[:dist], anch[:prefix], true)
90
+ end
91
+ end
92
+
93
+ self
49
94
  end
50
95
 
96
+ def inner_anchors(dist, prefix=:inner_, recreate=false)
97
+ @inner_anchor_defs ||= []
98
+ @inner_anchor_defs << { "dist": dist, "prefix": prefix } unless recreate
99
+
100
+ # $log.info "dist: #{dist}, prefix: #{prefix}"
101
+ sides = {
102
+ left: {x: dist, y: 0},
103
+ right: {x: -dist, y: 0},
104
+ top: {x: 0, y: -dist},
105
+ bottom: {x: 0, y: dist},
106
+ }
107
+ corners = {
108
+ top_left: {x: dist, y: -dist},
109
+ top_right: {x: -dist, y: -dist},
110
+ bottom_left: {x: dist, y: dist},
111
+ bottom_right: {x: -dist, y: dist},
112
+ }
113
+ new_sides = []
114
+ new_corners = []
115
+
116
+ sides.merge(corners).each do |key, vals|
117
+ new_dist = anchor(key).dup
118
+ new_dist[:x] += vals[:x]
119
+ new_dist[:y] += vals[:y]
120
+ name = [prefix, key].join.to_sym
121
+ # $log.info "Set anchor #{name} , new dist #{new_dist}"
122
+ set_anchor name, new_dist
123
+ if sides.include? key
124
+ new_sides << name
125
+ end
126
+ if corners.include? key
127
+ new_corners << name
128
+ end
129
+ end
130
+
131
+ sides_name = [prefix, "sides"].join
132
+ corners_name = [prefix, "corners"].join
133
+ all_name = [prefix, "all"].join
134
+ self.class.__send__(:attr_accessor, sides_name.to_sym)
135
+ self.class.__send__(:attr_accessor, corners_name.to_sym)
136
+ self.class.__send__(:attr_accessor, all_name.to_sym)
137
+ self.__send__("#{sides_name}=", new_sides)
138
+ self.__send__("#{corners_name}=", new_corners)
139
+ self.__send__("#{all_name}=", new_corners+new_sides)
140
+
141
+
142
+ self
143
+ end
144
+
145
+
51
146
  # used for openscad export
52
147
  def size
53
148
  [@x, @y, z+z_margin]
@@ -55,6 +150,7 @@ module JennCad::Primitives
55
150
 
56
151
  def not_centered
57
152
  @opts[:center] = false
153
+ set_anchors
58
154
  self
59
155
  end
60
156
  alias :nc :not_centered
@@ -62,20 +158,27 @@ module JennCad::Primitives
62
158
  def cx
63
159
  nc
64
160
  @opts[:center_x] = true
161
+ set_anchors
65
162
  self
66
163
  end
164
+ alias :center_x :cx
67
165
 
68
166
  def cy
69
167
  nc
70
168
  @opts[:center_y] = true
169
+ set_anchors
71
170
  self
72
171
  end
172
+ alias :center_y :cy
173
+
73
174
 
74
175
  def cz
75
176
  nc
76
177
  @opts[:center_z] = true
178
+ set_anchors
77
179
  self
78
180
  end
181
+ alias :center_z :cz
79
182
 
80
183
  def centered_axis
81
184
  return [:x, :y] if @opts[:center]
@@ -22,7 +22,7 @@ module JennCad::Primitives
22
22
  y: 0,
23
23
  z: nil,
24
24
  r: nil,
25
- flat_edges: nil,
25
+ flat_edges: [],
26
26
  center: true,
27
27
  center_y: false,
28
28
  center_x: false,
@@ -45,32 +45,42 @@ module JennCad::Primitives
45
45
  # make diameter not bigger than any side
46
46
  d = [@d, @x, @y].min
47
47
  res = HullObject.new(
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)
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
+ )
53
+ res = res.move(xy: d/2.0)
53
54
 
54
- res += flat_edge(@opts[:flat_edges])
55
+ @opts[:flat_edges].each do |edge|
56
+ res += apply_flat_edge(edge)
57
+ end
55
58
 
59
+ res = union(res) # put everything we have in a parent union that we can apply the transformations of this object of
56
60
  res.transformations = @transformations
61
+
57
62
  res.moveh(centered_axis.to_h{|a| [a, -@opts[a]] })
63
+ res.inherit_color(self)
58
64
  res
59
65
  end
60
66
 
61
- def flat_edge(edge)
67
+ def flat(edge)
68
+ @opts[:flat_edges] ||= []
69
+ @opts[:flat_edges] << edge
70
+ self
71
+ end
72
+
73
+ private
74
+ def apply_flat_edge(edge)
62
75
  case edge
63
- when Array
64
- #ruby2.7 test- edge.map(&self.:flat_edge)
65
- edge.map{|x| flat_edge(x) }
66
76
  when :up
67
- cube(@x, @y/2.0, @z).moveh(y:@y/2.0)
77
+ cube(x: @x, y: @y/2.0, z: @z).nc.moveh(y:@y)
68
78
  when :down
69
- cube(@x, @y/2.0, @z).moveh(y:-@y/2.0)
79
+ cube(x: @x, y: @y/2.0, z: @z).nc
70
80
  when :right
71
- cube(@x/2.0, @y, @z).moveh(x:@x/2.0)
81
+ cube(x: @x/2.0, y: @y, z: @z).nc.moveh(x:@x)
72
82
  when :left
73
- cube(@x/2.0, @y, @z).moveh(x:-@x/2.0)
83
+ cube(x: @x/2.0, y: @y, z: @z).nc
74
84
  else
75
85
  nil
76
86
  end
@@ -3,10 +3,16 @@ module JennCad::Primitives
3
3
  def inherit_z
4
4
  @z = 0
5
5
  @calc_z = parts.first.calc_z.to_f
6
+
6
7
  only_additives_of(@parts).each do |p|
8
+ if option(:debug)
9
+ $log.debug "inherit_z checks for: #{p}"
10
+ end
7
11
  z = p.z.to_f
8
12
  @z = z if z > @z
9
13
  end
14
+ $log.debug "inherit_z called, biggest z found: #{@z}" if option(:debug)
15
+
10
16
  end
11
17
 
12
18
  def get_heights(obj)
@@ -58,7 +64,7 @@ module JennCad::Primitives
58
64
  when JennCad::Circle
59
65
  when JennCad::BooleanObject
60
66
  else
61
- pp part if part.opts[:debug]
67
+ $log.debug part if part.opts[:debug]
62
68
  part.opts[:margins][:z] ||= 0.0
63
69
  unless part.opts[:margins][:z] == 0.2
64
70
  part.opts[:margins][:z] = 0.2
@@ -66,7 +72,7 @@ module JennCad::Primitives
66
72
  end
67
73
  end
68
74
  elsif part.z == compare_h
69
- # puts "fixing possible z fighting: #{part.class} #{part.z}"
75
+ $log.debug "fixing possible z fighting: #{part.class} #{part.z}" if part.opts[:debug]
70
76
  part.opts[:margins][:z] += 0.008
71
77
  part.mz(-0.004)
72
78
  elsif part.calc_z == compare_z
@@ -1,34 +1,34 @@
1
1
  module JennCad
2
2
  def circle(args)
3
- Circle.new(args)
3
+ Circle.new(args).set_parent(self)
4
4
  end
5
5
 
6
6
  def cylinder(*args)
7
- Cylinder.new(args)
7
+ Cylinder.new(args).set_parent(self)
8
8
  end
9
9
  alias :cy :cylinder
10
10
  alias :cyl :cylinder
11
11
 
12
12
  def sphere(args)
13
- Sphere.new(args)
13
+ Sphere.new(args).set_parent(self)
14
14
  end
15
15
  alias :sp :sphere
16
16
 
17
17
  def polygon(args)
18
- Polygon.new(args)
18
+ Polygon.new(args).set_parent(self)
19
19
  end
20
20
 
21
21
  def slot(*args)
22
- Slot.new(args)
22
+ Slot.new(args).set_parent(self)
23
23
  end
24
24
 
25
25
  def cube(*args)
26
- Cube.new(args)
26
+ Cube.new(args).set_parent(self)
27
27
  end
28
28
  alias :cu :cube
29
29
 
30
30
  def rounded_cube(*args)
31
- RoundedCube.new(args)
31
+ RoundedCube.new(args).set_parent(self)
32
32
  end
33
33
  alias :rcube :rounded_cube
34
34
  alias :rc :rounded_cube
@@ -39,7 +39,7 @@ module JennCad
39
39
  end
40
40
 
41
41
  def stl(file, args={})
42
- StlImport.new(file, args)
42
+ StlImport.new(file, args).set_parent(self)
43
43
  end
44
44
 
45
45
  def extrude(args={})
data/lib/jenncad/thing.rb CHANGED
@@ -7,7 +7,8 @@ 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
+ attr_accessor :anchors
11
+ attr_accessor :parent
11
12
 
12
13
  def initialize(args={})
13
14
  @transformations = []
@@ -16,6 +17,8 @@ module JennCad
16
17
  @calc_y = 0
17
18
  @calc_z = 0
18
19
  @calc_h = args[:z] || 0
20
+ @anchors = {}
21
+ @parent = args[:parent]
19
22
  @opts ||= args
20
23
  end
21
24
 
@@ -29,34 +32,30 @@ module JennCad
29
32
  @opts[key] = val
30
33
  end
31
34
 
32
- def set_anchor(args)
33
- self.anchor ||= {}
34
- args.each do |key, val|
35
- self.anchor[key] = val
36
- end
35
+ def set_parent(parent)
36
+ @parent = parent
37
+ self
37
38
  end
38
39
 
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)
40
+ def anchor(name, thing=nil)
41
+ if thing
42
+ return thing.anchor(name)
47
43
  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
44
+ @anchors ||= {}
45
+ if anch = @anchors[name]
46
+ return anch
47
+ elsif @parent
48
+ return @parent.anchor(name)
56
49
  end
57
- move(to)
58
50
  end
51
+ alias :a :anchor
59
52
 
53
+ def set_anchor(name, args={})
54
+ @anchors ||= {}
55
+ @anchors[name] = args
56
+ self
57
+ end
58
+ alias :sa :set_anchor
60
59
 
61
60
  def auto_extrude
62
61
  ret = self.extrude
@@ -138,10 +137,18 @@ module JennCad
138
137
  end
139
138
 
140
139
  def parse_xyz_shortcuts(args)
140
+ unless args.kind_of? Hash
141
+ $log.warn "parse_xyz_shortcuts called for type #{args.class} #{args.inspect}"
142
+ return args
143
+ end
141
144
  [:x, :y, :z].each do |key|
142
145
  args[key] ||= 0.0
143
146
  end
144
147
 
148
+ if args[:debug]
149
+ $log.debug "Args: #{args}"
150
+ end
151
+
145
152
  if args[:xy]
146
153
  args[:x] += args[:xy]
147
154
  args[:y] += args[:xy]
@@ -159,7 +166,11 @@ module JennCad
159
166
  args[:y] += args[:yz]
160
167
  args[:z] += args[:yz]
161
168
  end
162
- return args
169
+ if args[:debug]
170
+ $log.debug "After xyz shortcuts #{args}"
171
+ end
172
+
173
+ return args
163
174
  end
164
175
 
165
176
  def move(args={})
@@ -195,6 +206,31 @@ module JennCad
195
206
  move(z:v)
196
207
  end
197
208
 
209
+ # move to anchor
210
+ def movea(key, thing=nil)
211
+ an = anchor(key, thing)
212
+ unless an
213
+ $log.error "Error: Anchor #{key} not found"
214
+ $log.error "Available anchors: #{@anchors}"
215
+ return self
216
+ else
217
+ self.move(an.dup)
218
+ end
219
+ end
220
+
221
+ # move to anchor - inverted
222
+ def moveai(key, thing=nil)
223
+ an = anchor(key, thing)
224
+ unless an
225
+ $log.error "Error: Anchor #{key} not found"
226
+ $log.error "Available anchors: #{@anchors}"
227
+ return self
228
+ else
229
+ self.movei(an.dup)
230
+ end
231
+ end
232
+
233
+
198
234
  # move half
199
235
  def moveh(args={})
200
236
  if args.kind_of? Array
@@ -221,6 +257,16 @@ module JennCad
221
257
  moveh(z:v)
222
258
  end
223
259
 
260
+ def movei(args={})
261
+ to = {}
262
+ [:x, :y, :z, :xy, :xz, :yz, :xyz].each do |key|
263
+ if args[key]
264
+ to[key] = args[key]*-1
265
+ end
266
+ end
267
+ move(to)
268
+ end
269
+
224
270
  def mirror(args={})
225
271
  @transformations ||= []
226
272
  @transformations << Mirror.new(args)
@@ -228,6 +274,19 @@ module JennCad
228
274
  end
229
275
  alias :mi :mirror
230
276
 
277
+ def miz
278
+ mirror(z:1)
279
+ end
280
+
281
+ def miy
282
+ mirror(y:1)
283
+ end
284
+
285
+ def miz
286
+ mirror(z:1)
287
+ end
288
+
289
+
231
290
  def scale(args={})
232
291
  if args.kind_of? Numeric or args.kind_of? Array
233
292
  args = {v:args}
@@ -313,6 +372,11 @@ module JennCad
313
372
  end
314
373
  =end
315
374
 
375
+ def inherit_color(other)
376
+ self.set_option(:color, other.option(:color))
377
+ self.set_option(:auto_color, other.option(:auto_color))
378
+ end
379
+
316
380
  def has_explicit_color?
317
381
  if option(:auto_color) == false
318
382
  return true
@@ -465,6 +529,37 @@ module JennCad
465
529
  JennCad::Exporters::OpenScad.new(self).save(file)
466
530
  end
467
531
 
532
+ def ghost
533
+ set_option :ghost, true
534
+ set_option :no_auto_color, true
535
+ set_option :color, nil
536
+ set_option :auto_color, false
537
+ self
538
+ end
539
+
540
+ def hide
541
+ set_option :hide, true
542
+ self
543
+ end
544
+
545
+ def only
546
+ set_option :only, true
547
+ self
548
+ end
549
+
550
+ def hl
551
+ set_option :highlight, true
552
+ self
553
+ end
554
+
555
+ def openscad_modifier
556
+ return "%" if option(:ghost)
557
+ return "#" if option(:highlight)
558
+ return "!" if option(:only)
559
+ return "*" if option(:hide)
560
+ nil
561
+ end
562
+
468
563
  def referenced_z
469
564
  return false if @z.to_f != 0.0
470
565
  return option(:zref) if option(:zref)
@@ -1,4 +1,4 @@
1
1
  module JennCad
2
- VERSION = "1.0.0-alpha9"
2
+ VERSION = "1.0.0-alpha12"
3
3
  end
4
4
 
data/lib/jenncad.rb CHANGED
@@ -1,3 +1,6 @@
1
+ require "logger"
2
+ $log = Logger.new(STDOUT)
3
+
1
4
  require "geo3d"
2
5
  require "deep_merge"
3
6
  require "fileutils"
data/todo.txt CHANGED
@@ -1,29 +1,59 @@
1
1
  1.0 required features
2
2
  ===================
3
3
 
4
- - cli needs to be a package manager for existing parts from a public library (i.e. bolts, motors go here), able to
5
- -- query
6
- -- download
7
- -- update
8
- (upload? -> probably git pull request for now)
9
- - add external projects into one another (for example: make parts, show arrangement of a shelf in another project)
10
-
11
4
  - slot with square ends -> rounded cube with one side = d + flat_edges does that. Should slot do that in reverse?
12
5
 
13
- - de-centering a cube in one direction sucks, you have to add both center: false, center_x: true
14
- -> decenter ?
15
-
16
6
  - bolt library needs to get a rewrite,
17
7
  - fetching dimensions from the imported Bolt library should be less awful
18
8
 
19
9
  - needs a documentation and showcase
20
10
 
11
+ Features wanted
12
+ ===================
13
+ 28.4.22:
14
+ - Parts often come with 4 holes around a center, and I often do something like:
15
+
16
+ [-1, 1].each do |i|
17
+ [-1, 1].each do |j|
18
+ res += @bolt.cut.move(x: @hole_center*i, y: @hole_center*j)
19
+ end
20
+ end
21
+
22
+ there should be a shorter way to do this.
23
+
24
+
25
+ - instead of moving Bolts output, make it the default to make their positions an anchor
26
+
27
+ - Bolt size data should be in a constant instead of one "Data" constant i.e.
28
+ M2_5.head_dia
29
+ M2_5.head_h
30
+ M2_5_hole
31
+
32
+ - Bolt sizes should follow user configuration that can change margins
33
+ - Bolts should have an easier way to align than mirror them, maybe from :top
34
+ - 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..
35
+ - Bolts should be able to also make thread inserts
36
+
37
+
38
+
39
+
21
40
  other awful things
22
41
  ===================
23
42
 
24
- - command line interface isn't capable of adding parts to the output automatically
43
+ - cli needs to use templates and user defined templates, profile loader needs to have this.
25
44
 
26
45
  - user profile file should be auto generated with examples
27
46
 
28
- - switching back and forth from and to openscad for preview sucks (that being said, switching from vim to something else would be awful to me)
47
+
48
+ Future plans
49
+ ==================
50
+
51
+ - cli needs to be a package manager for existing parts from a public library (i.e. bolts, motors go here), able to
52
+ -- query
53
+ -- download
54
+ -- update
55
+ (upload? -> probably git pull request for now)
56
+ - add external projects into one another (for example: make parts, show arrangement of a shelf in another project)
57
+
58
+
29
59
 
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.alpha9
4
+ version: 1.0.0.pre.alpha12
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-04-24 00:00:00.000000000 Z
11
+ date: 2022-04-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: geo3d
@@ -80,6 +80,20 @@ dependencies:
80
80
  - - ">="
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: logger
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
83
97
  description: TBD
84
98
  email:
85
99
  - "=^.^=@jenncad.kittenme.ws"
@@ -88,17 +102,11 @@ executables:
88
102
  extensions: []
89
103
  extra_rdoc_files: []
90
104
  files:
105
+ - LICENSE
91
106
  - README.md
92
107
  - Rakefile
93
108
  - bin/jenncad
94
- - examples/old/cube.rb
95
- - examples/old/slot.rb
96
- - examples/old/test.rb
97
- - examples/old/test1.rb
98
- - examples/old/test2.rb
99
- - examples/old/test3.rb
100
- - examples/old/test4.rb
101
- - examples/old/test5.rb
109
+ - examples/README
102
110
  - jenncad.gemspec
103
111
  - lib/jenncad.rb
104
112
  - lib/jenncad/commands.rb
data/examples/old/cube.rb DELETED
@@ -1,12 +0,0 @@
1
- require 'rubygems'
2
- require 'jenncad'
3
- include JennCad
4
-
5
- # cubes are centered in x,y and flat to z=0 by default
6
- res = cube(40,30,20)
7
- # if symbols are omitted first argument of cylinder is d (diameter), second is height
8
- # if height is omitted, it will assume height of first suitable parent object. This only works for z direction
9
- # if height is omitted, it will also reward you with automatic z-fighting. For other cuts it'll try to do the same but is not so smart
10
- res -= cylinder(5)
11
-
12
- res.openscad("cube.scad")
data/examples/old/slot.rb DELETED
@@ -1,10 +0,0 @@
1
- require 'rubygems'
2
- require 'jenncad'
3
- include JennCad
4
-
5
- res = cube(30,30,10)
6
-
7
- res -= slot(d:10, x:20, a:30).move(x:5)
8
- res -= slot(d:10, x:20, a:-30).move(x:5)
9
-
10
- res.openscad("slot.scad")
data/examples/old/test.rb DELETED
@@ -1,18 +0,0 @@
1
- require 'jenncad'
2
- include JennCad
3
- include JennCad::Extras
4
- Nut = Din934
5
-
6
- res = cylinder(d:40,h:20)
7
-
8
- n = Nut.new(4)
9
- res -= n.cut
10
-
11
- n = Nut.new(4)
12
- res -= n.cut.translate(x:20)
13
- res += n.show.translate(x:20)
14
-
15
-
16
-
17
- a = OpenScad.new(res)
18
- a.save("examples/test1.scad")
@@ -1,21 +0,0 @@
1
- require 'rubygems'
2
- require 'jenncad'
3
- include JennCad
4
- include JennCad::Extras
5
- Nut = Din934
6
-
7
- h1 = 10
8
- h2 = 20
9
- res = cube([10,20,h1])
10
- res += cylinder(d:40,h:h2).move(z:h1)
11
-
12
-
13
- n = Nut.new(4)
14
- res -= n.cut
15
-
16
- n = Nut.new(4)
17
- res -= n.cut.move(z:h1+h2-n.height)
18
-
19
-
20
-
21
- res.openscad("examples/test1.scad")
@@ -1,9 +0,0 @@
1
- require 'jenncad'
2
- include JennCad
3
-
4
- res = import("involute_gears","bevel_gear",number_of_teeth:13, bore_diameter:10)
5
- res += import("involute_gears","bevel_gear",number_of_teeth:6, bore_diameter:5).rotate(x:90).translate(y:50,z:30)
6
-
7
-
8
- a = OpenScad.new(res)
9
- a.save("examples/test2.scad")
@@ -1,15 +0,0 @@
1
- require 'rubygems'
2
- require 'jenncad'
3
- include JennCad
4
- include JennCad::Extras
5
- Nut = Din934
6
-
7
- res = cylinder(d:40,h:20)
8
- res &= cylinder(d:40,h:20).translate(x:20)
9
- res &= cube([20,20,20]).translate(y:20)
10
-
11
- res.skew(y:-0.3)
12
-
13
-
14
- a = OpenScad.new(res)
15
- a.save("examples/test3.scad")
@@ -1,17 +0,0 @@
1
- require 'rubygems'
2
- require 'jenncad'
3
- include JennCad
4
- include JennCad::Extras
5
- Nut = Din934
6
-
7
- res = cube([30,30,10]).center_xy
8
- res -= cylinder(d:20,h:2)
9
-
10
- cyl = cylinder(d:10,h:5).translate(z:5)
11
- res -= cyl
12
-
13
- puts cyl.calc_z+cyl.calc_h
14
-
15
-
16
- a = OpenScad.new(res)
17
- a.save("examples/test4.scad")
@@ -1,31 +0,0 @@
1
- require 'rubygems'
2
- require 'jenncad'
3
- include JennCad
4
- include JennCad::Extras
5
- Nut = Din934
6
-
7
- res = cube([30,30,10]).center_xy
8
- # at this moment, res is a cube
9
- res.color = "Blue"
10
-
11
- res += cylinder(d:10,h:20)
12
- # with the += operator, res is now a union boolean object
13
- res.color [120,20,13,200]
14
-
15
- # everything added to the union will remain this color
16
- res += cylinder(d:6,h:25)
17
-
18
- # unless specified otherwise
19
- res += cylinder(d:5, h:30).color("red")
20
-
21
-
22
-
23
- # subtracting will change res to a subtraction object
24
- res -= cylinder(d:4, h:30)
25
- res += cylinder(d:2, h:40)
26
- res.color("green")
27
-
28
-
29
-
30
- a = OpenScad.new(res)
31
- a.save("examples/test5.scad")