solidruby 0.1.0
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 +7 -0
- data/.gitignore +4 -0
- data/.travis.yml +3 -0
- data/COPYING +674 -0
- data/Gemfile +2 -0
- data/Guardfile +24 -0
- data/LICENSE.md +675 -0
- data/README.md +180 -0
- data/Rakefile +10 -0
- data/bin/solidruby +61 -0
- data/examples/chamfered_cube.rb +39 -0
- data/examples/filleted_cube.rb +39 -0
- data/examples/gear.rb +11 -0
- data/examples/knurls.rb +12 -0
- data/examples/nut_support.rb +17 -0
- data/examples/openscad_examples/old/example001.rb +42 -0
- data/examples/openscad_examples/old/example002.rb +45 -0
- data/examples/openscad_examples/old/example003.rb +37 -0
- data/examples/openscad_examples/old/example004.rb +22 -0
- data/examples/openscad_examples/old/example005.rb +45 -0
- data/examples/openscad_examples/old/example006.rb +85 -0
- data/examples/openscad_examples/old/example007.dxf +2410 -0
- data/examples/openscad_examples/old/example007.rb +107 -0
- data/examples/openscad_examples/old/example008.rb +61 -0
- data/examples/openscad_examples/old/example009.dxf +3894 -0
- data/examples/openscad_examples/old/example009.rb.old +48 -0
- data/examples/openscad_examples/old/example010.dat +51 -0
- data/examples/openscad_examples/old/example010.rb +23 -0
- data/examples/openscad_examples/old/example011.rb +42 -0
- data/examples/openscad_examples/old/example012.rb +22 -0
- data/examples/openscad_examples/old/example012.stl +450 -0
- data/examples/openscad_examples/old/example013.dxf +2276 -0
- data/examples/openscad_examples/old/example013.rb +30 -0
- data/examples/openscad_examples/old/example014.rb +30 -0
- data/examples/openscad_examples/old/example015.rb +46 -0
- data/examples/openscad_examples/old/example016.rb +75 -0
- data/examples/openscad_examples/old/example016.stl +0 -0
- data/examples/pipe.rb +38 -0
- data/examples/pipe_bug.rb +16 -0
- data/examples/printed_gear.rb +12 -0
- data/examples/printed_gear2.rb +16 -0
- data/examples/printed_thread.rb +9 -0
- data/examples/printed_thread2.rb +13 -0
- data/examples/stack.rb +21 -0
- data/examples/threads.rb +183 -0
- data/examples/threads2.rb +93 -0
- data/examples/threads3.rb +46 -0
- data/lib/solidruby.rb +60 -0
- data/lib/solidruby/assemblies/assembly.rb +176 -0
- data/lib/solidruby/assemblies/bolt.rb +158 -0
- data/lib/solidruby/assemblies/gear.rb +131 -0
- data/lib/solidruby/assemblies/linear_bearing.rb +84 -0
- data/lib/solidruby/assemblies/nut.rb +153 -0
- data/lib/solidruby/assemblies/pipe.rb +153 -0
- data/lib/solidruby/assemblies/ruler.rb +44 -0
- data/lib/solidruby/assemblies/tslot.rb +141 -0
- data/lib/solidruby/assemblies/tslot_machining.rb +62 -0
- data/lib/solidruby/assemblies/washer.rb +57 -0
- data/lib/solidruby/bill_of_material.rb +43 -0
- data/lib/solidruby/csg_modelling/csg_modelling.rb +43 -0
- data/lib/solidruby/csg_modelling/difference.rb +41 -0
- data/lib/solidruby/csg_modelling/hull.rb +23 -0
- data/lib/solidruby/csg_modelling/intersection.rb +24 -0
- data/lib/solidruby/csg_modelling/minkowski.rb +23 -0
- data/lib/solidruby/csg_modelling/union.rb +41 -0
- data/lib/solidruby/csg_modifiers/color.rb +41 -0
- data/lib/solidruby/csg_modifiers/csg_modifier.rb +50 -0
- data/lib/solidruby/csg_modifiers/linear_extrude.rb +34 -0
- data/lib/solidruby/csg_modifiers/projection.rb +29 -0
- data/lib/solidruby/csg_modifiers/rotate_extrude.rb +30 -0
- data/lib/solidruby/extra.rb +58 -0
- data/lib/solidruby/helpers/chamfer.rb +27 -0
- data/lib/solidruby/helpers/fillet.rb +28 -0
- data/lib/solidruby/helpers/position.rb +267 -0
- data/lib/solidruby/helpers/rounded_cube.rb +37 -0
- data/lib/solidruby/helpers/triangle.rb +167 -0
- data/lib/solidruby/primitives/circle.rb +26 -0
- data/lib/solidruby/primitives/cube.rb +123 -0
- data/lib/solidruby/primitives/cylinder.rb +72 -0
- data/lib/solidruby/primitives/import.rb +42 -0
- data/lib/solidruby/primitives/polygon.rb +26 -0
- data/lib/solidruby/primitives/polyhedron.rb +30 -0
- data/lib/solidruby/primitives/primitive.rb +19 -0
- data/lib/solidruby/primitives/render.rb +48 -0
- data/lib/solidruby/primitives/sphere.rb +49 -0
- data/lib/solidruby/primitives/square.rb +88 -0
- data/lib/solidruby/primitives/surface.rb +44 -0
- data/lib/solidruby/primitives/text.rb +43 -0
- data/lib/solidruby/printed_thread.rb +163 -0
- data/lib/solidruby/rubyscad_bridge.rb +376 -0
- data/lib/solidruby/screw_thread.rb +170 -0
- data/lib/solidruby/solidruby.rb +150 -0
- data/lib/solidruby/solidruby_object.rb +176 -0
- data/lib/solidruby/transformations/mirror.rb +22 -0
- data/lib/solidruby/transformations/rotate.rb +22 -0
- data/lib/solidruby/transformations/scale.rb +22 -0
- data/lib/solidruby/transformations/transformation.rb +29 -0
- data/lib/solidruby/transformations/translate.rb +32 -0
- data/lib/solidruby/version.rb +18 -0
- data/lib/templates/assembly.tt +13 -0
- data/lib/templates/gitignore.tt +3 -0
- data/lib/templates/guardfile.tt +4 -0
- data/lib/templates/main.tt +20 -0
- data/lib/templates/params.tt +3 -0
- data/lib/templates/printed.tt +9 -0
- data/manual/manual.html +417 -0
- data/solidruby.gemspec +35 -0
- metadata +277 -0
|
@@ -0,0 +1,376 @@
|
|
|
1
|
+
# This file is part of SolidRuby.
|
|
2
|
+
#
|
|
3
|
+
# SolidRuby is free software: you can redistribute it and/or modify
|
|
4
|
+
# it under the terms of the GNU General Public License as published by
|
|
5
|
+
# the Free Software Foundation, either version 3 of the License, or
|
|
6
|
+
# (at your option) any later version.
|
|
7
|
+
#
|
|
8
|
+
# SolidRuby is distributed in the hope that it will be useful,
|
|
9
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
10
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
11
|
+
# GNU General Public License for more details.
|
|
12
|
+
#
|
|
13
|
+
# You should have received a copy of the GNU General Public License
|
|
14
|
+
# along with SolidRuby. If not, see <http://www.gnu.org/licenses/>.
|
|
15
|
+
#
|
|
16
|
+
#
|
|
17
|
+
# This code is based on RubyScad (https://github.com/cjbissonnette/RubyScad)
|
|
18
|
+
# which is GPLv3
|
|
19
|
+
#
|
|
20
|
+
require 'matrix'
|
|
21
|
+
|
|
22
|
+
module SolidRuby
|
|
23
|
+
class RubyScadBridge
|
|
24
|
+
START_BLOCK = '{'.freeze
|
|
25
|
+
END_BLOCK = '}'.freeze
|
|
26
|
+
TAB_SIZE = 3
|
|
27
|
+
PAD = 0.01
|
|
28
|
+
FP_P = 3
|
|
29
|
+
|
|
30
|
+
CUBE_STR = 'cube(%<args>s);'.freeze
|
|
31
|
+
SPHERE_STR = 'sphere(%<args>s);'.freeze
|
|
32
|
+
CYLINDER_STR = 'cylinder(%<args>s);'.freeze
|
|
33
|
+
POLYHEDRON_STR = 'polyhedron(%<args>s);'.freeze
|
|
34
|
+
SQUARE_STR = 'square(%<args>s);'.freeze
|
|
35
|
+
CIRCLE_STR = 'circle(%<args>s);'.freeze
|
|
36
|
+
POLYGON_STR = 'polygon(%<args>s);'.freeze
|
|
37
|
+
TRANSLATE_STR = 'translate(%<args>s)'.freeze
|
|
38
|
+
ROTATE_STR = 'rotate(%<args>s)'.freeze
|
|
39
|
+
SCALE_STR = 'scale(%<args>s)'.freeze
|
|
40
|
+
MIRROR_STR = 'mirror(%<args>s)'.freeze
|
|
41
|
+
MULTMATRIX_STR = 'multmatrix(%<args>s)'.freeze
|
|
42
|
+
COLOR_STR = 'color(%<args>s)'.freeze
|
|
43
|
+
UNION_STR = 'union(%<args>s)'.freeze
|
|
44
|
+
DIFFERENCE_STR = 'difference(%<args>s)'.freeze
|
|
45
|
+
INTERSECTION_STR = 'intersection(%<args>s)'.freeze
|
|
46
|
+
RENDER_STR = 'render(%<args>s)'.freeze
|
|
47
|
+
MINKOWSKI_STR = 'minkowski(%<args>s)'.freeze
|
|
48
|
+
HULL_STR = 'hull(%<args>s)'.freeze
|
|
49
|
+
BACKGROUND_STR = '%'.freeze
|
|
50
|
+
DEBUG_STR = '#'.freeze
|
|
51
|
+
ROOT_STR = '!'.freeze
|
|
52
|
+
DISABLE_STR = '*'.freeze
|
|
53
|
+
IMPORT_STR = 'import(%<args>s);'.freeze
|
|
54
|
+
SURFACE_STR = 'surface(%<args>s);'.freeze
|
|
55
|
+
LINEAR_EXTRUDE_STR = 'linear_extrude(%<args>s)'.freeze
|
|
56
|
+
ROTATE_EXTRUDE_STR = 'rotate_extrude(%<args>s)'.freeze
|
|
57
|
+
PROJECTION_STR = 'projection(%<args>s)'.freeze
|
|
58
|
+
TEXT_STR = 'text(%<args>s);'.freeze
|
|
59
|
+
|
|
60
|
+
INCLUDE_STR = 'include <%<file>s>'.freeze
|
|
61
|
+
USE_STR = 'use <%<file>s>'.freeze
|
|
62
|
+
ECHO_STR = 'echo(%<string>s);'.freeze
|
|
63
|
+
FA_STR = '$fa = %<value>s;'.freeze
|
|
64
|
+
FS_STR = '$fs = %<value>s;'.freeze
|
|
65
|
+
FN_STR = '$fn = %<value>s;'.freeze
|
|
66
|
+
|
|
67
|
+
def fa(value)
|
|
68
|
+
format_output FA_STR % { value: value }
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def fs(value)
|
|
72
|
+
format_output FS_STR % { value: value }
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def fn(value)
|
|
76
|
+
format_output FN_STR % { value: value }
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def include_scad(file)
|
|
80
|
+
format_output INCLUDE_STR % { file: file }
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def use(file)
|
|
84
|
+
format_output USE_STR % { file: file }
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def echo(*args)
|
|
88
|
+
format_output ECHO_STR % { string: args.join(', ') }
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def projection(args = {}, &block)
|
|
92
|
+
format_command PROJECTION_STR, args, &block
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def linear_extrude(args = {}, &block)
|
|
96
|
+
str_end = args.include?(:file) ? ';' : ''
|
|
97
|
+
format_command LINEAR_EXTRUDE_STR.concat(str_end), args, &block
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def rotate_extrude(args = {}, &block)
|
|
101
|
+
str_end = args.include?(:file) ? ';' : ''
|
|
102
|
+
format_command ROTATE_EXTRUDE_STR.concat(str_end), args, &block
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def import(args = {})
|
|
106
|
+
format_command IMPORT_STR, args
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def difference(&block)
|
|
110
|
+
format_command DIFFERENCE_STR, &block
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def union(&block)
|
|
114
|
+
format_command UNION_STR, &block
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def intersection(&block)
|
|
118
|
+
format_command INTERSECTION_STR, &block
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def render(args = {}, &block)
|
|
122
|
+
format_command RENDER_STR, args, &block
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def minkowski(&block)
|
|
126
|
+
format_command MINKOWSKI_STR, &block
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def hull(&block)
|
|
130
|
+
format_command HULL_STR, &block
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def background
|
|
134
|
+
format_output BACKGROUND_STR
|
|
135
|
+
yield if block_given?
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def debug
|
|
139
|
+
format_output DEBUG_STR
|
|
140
|
+
yield if block_given?
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def root
|
|
144
|
+
format_output ROOT_STR
|
|
145
|
+
yield if block_given?
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def disable
|
|
149
|
+
format_output DISABLE_STR
|
|
150
|
+
yield if block_given?
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
def cube(args = {})
|
|
154
|
+
format_command CUBE_STR, args
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def sphere(args = {})
|
|
158
|
+
if args.include?(:d)
|
|
159
|
+
args[:r] = args[:d] / 2.0
|
|
160
|
+
args.delete(:d)
|
|
161
|
+
end
|
|
162
|
+
format_command SPHERE_STR, args
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
def polyhedron(args = {})
|
|
166
|
+
format_command POLYHEDRON_STR, args
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
def square(args = {})
|
|
170
|
+
format_command SQUARE_STR, args
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
def circle(args = {})
|
|
174
|
+
if args.include?(:d)
|
|
175
|
+
args[:r] = args[:d] / 2.0
|
|
176
|
+
args.delete(:d)
|
|
177
|
+
end
|
|
178
|
+
format_command CIRCLE_STR, args
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
def polygon(args = {})
|
|
182
|
+
format_command POLYGON_STR, args
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
def surface(args = {})
|
|
186
|
+
format_command SURFACE_STR, args
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
def cylinder(args = {})
|
|
190
|
+
if args.include?(:d)
|
|
191
|
+
args[:r] = args[:d] / 2.0
|
|
192
|
+
args.delete(:d)
|
|
193
|
+
end
|
|
194
|
+
if args.include?(:d1)
|
|
195
|
+
args[:r1] = args[:d1] / 2.0
|
|
196
|
+
args.delete(:d1)
|
|
197
|
+
end
|
|
198
|
+
if args.include?(:d2)
|
|
199
|
+
args[:r2] = args[:d2] / 2.0
|
|
200
|
+
args.delete(:d2)
|
|
201
|
+
end
|
|
202
|
+
format_command CYLINDER_STR, args
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
def text(args = {})
|
|
206
|
+
format_command TEXT_STR, args
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
def rotate(args = {}, &block)
|
|
210
|
+
vector_input(args, :a)
|
|
211
|
+
format_command ROTATE_STR, args, &block
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
def translate(args = {}, &block)
|
|
215
|
+
delete_from(args, :z) if args[:z] == 0
|
|
216
|
+
vector_input(args, :v)
|
|
217
|
+
format_command TRANSLATE_STR, args, &block
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
def scale(args = {}, &block)
|
|
221
|
+
vector_input(args, :v)
|
|
222
|
+
format_command SCALE_STR, args, &block
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
def mirror(args = {}, &block)
|
|
226
|
+
vector_input(args, :v)
|
|
227
|
+
format_command MIRROR_STR, args, &block
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
def multmatrix(args = {}, &block)
|
|
231
|
+
format_command MULTMATRIX_STR, args, &block
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
def color(args = {}, &block)
|
|
235
|
+
if args.include?(:color)
|
|
236
|
+
args[:color] = "\"#{args[:color]}\""
|
|
237
|
+
else
|
|
238
|
+
args[:color] = [args.fetch(:r, 0), args.fetch(:g, 0), args.fetch(:b, 0), args.fetch(:a, 1)].to_s
|
|
239
|
+
end
|
|
240
|
+
delete_from(args, :r, :g, :b, :a)
|
|
241
|
+
format_command(COLOR_STR, args[:color], &block)
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
def format_command(cmd_str, args = {}, &block)
|
|
245
|
+
if args.is_a? String
|
|
246
|
+
arg_str = args
|
|
247
|
+
else
|
|
248
|
+
arg_str = args.collect do
|
|
249
|
+
|k, v| "#{format_key(k)} = #{format_value(v)}"
|
|
250
|
+
end
|
|
251
|
+
.sort_by{ |x| ['$fn', '$fa', '$fs', 'cen', 'con'].include?(x[0..2]) ? ('z' + x) : x }
|
|
252
|
+
.join(', ')
|
|
253
|
+
end
|
|
254
|
+
format_block cmd_str % { args: arg_str }, &block
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
def format_key(key)
|
|
258
|
+
key = key.to_s
|
|
259
|
+
key.prepend('$') if key.match('^f[asn]$')
|
|
260
|
+
key
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
def format_value(var)
|
|
264
|
+
if var.nil?
|
|
265
|
+
"nil"
|
|
266
|
+
elsif var.is_a?(Vector) || var.is_a?(Matrix) || var.is_a?(Array)
|
|
267
|
+
res = []
|
|
268
|
+
var.to_a.each do |v|
|
|
269
|
+
res << format_value(v)
|
|
270
|
+
end
|
|
271
|
+
res.to_s.gsub('"', "").gsub('\\', '')
|
|
272
|
+
elsif var.is_a? String
|
|
273
|
+
'"' + var + '"'
|
|
274
|
+
elsif var.is_a? Float
|
|
275
|
+
"%.#{FP_P}f" % var.round(FP_P).to_s
|
|
276
|
+
else
|
|
277
|
+
var.to_s
|
|
278
|
+
end
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
def delete_from(hash, *keys)
|
|
282
|
+
keys.each { |k| hash.delete(k) }
|
|
283
|
+
end
|
|
284
|
+
|
|
285
|
+
def vector_input(args, element)
|
|
286
|
+
unless args.include?(element)
|
|
287
|
+
args[element] = [args.fetch(:x, 0), args.fetch(:y, 0)]
|
|
288
|
+
args[element].push(args[:z]) if args.include?(:z)
|
|
289
|
+
delete_from(args, :x, :y, :z)
|
|
290
|
+
end
|
|
291
|
+
end
|
|
292
|
+
|
|
293
|
+
def new_line
|
|
294
|
+
format_output "\n"
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
def start_block
|
|
298
|
+
format_output START_BLOCK
|
|
299
|
+
end
|
|
300
|
+
|
|
301
|
+
def end_block
|
|
302
|
+
format_output END_BLOCK
|
|
303
|
+
end
|
|
304
|
+
|
|
305
|
+
def end_all_blocks
|
|
306
|
+
end_block while @@tab_level > 0
|
|
307
|
+
end
|
|
308
|
+
|
|
309
|
+
def space_string(str, tab_level)
|
|
310
|
+
((' ' * TAB_SIZE) * tab_level) + str
|
|
311
|
+
end
|
|
312
|
+
|
|
313
|
+
def raw_output(str)
|
|
314
|
+
str
|
|
315
|
+
end
|
|
316
|
+
|
|
317
|
+
def format_output(str)
|
|
318
|
+
str
|
|
319
|
+
end
|
|
320
|
+
|
|
321
|
+
def format_block(output_str)
|
|
322
|
+
output_str
|
|
323
|
+
end
|
|
324
|
+
|
|
325
|
+
def self.start_output
|
|
326
|
+
@@output_file ||= nil
|
|
327
|
+
if ARGV[0] && ARGV[0].include?('.scad')
|
|
328
|
+
@@output_file = ARGV[0]
|
|
329
|
+
ARGV.shift
|
|
330
|
+
end
|
|
331
|
+
if @@output_file
|
|
332
|
+
File.open(@@output_file, 'w') do |f|
|
|
333
|
+
f.puts "//created with rubyscad #{VERSION}\n\n"
|
|
334
|
+
end
|
|
335
|
+
end
|
|
336
|
+
end
|
|
337
|
+
|
|
338
|
+
def self.extended(_mod)
|
|
339
|
+
start_output
|
|
340
|
+
end
|
|
341
|
+
|
|
342
|
+
def self.included(_mod)
|
|
343
|
+
start_output
|
|
344
|
+
end
|
|
345
|
+
|
|
346
|
+
start_output if __FILE__ == $PROGRAM_NAME
|
|
347
|
+
|
|
348
|
+
def lookup(x, points)
|
|
349
|
+
xmin = 0.0
|
|
350
|
+
xmax = 0.0
|
|
351
|
+
points.keys.sort.reverse_each do |k|
|
|
352
|
+
if k <= x
|
|
353
|
+
xmin = k
|
|
354
|
+
break
|
|
355
|
+
end
|
|
356
|
+
end
|
|
357
|
+
points.keys.sort.each do |k|
|
|
358
|
+
if k >= x
|
|
359
|
+
xmax = k
|
|
360
|
+
break
|
|
361
|
+
end
|
|
362
|
+
end
|
|
363
|
+
return points[xmax] if x == xmax
|
|
364
|
+
return points[xmin] if x == xmin
|
|
365
|
+
points[xmin] + (((x - xmin) * (points[xmax] - points[xmin])) / (xmax - xmin))
|
|
366
|
+
end
|
|
367
|
+
|
|
368
|
+
def dxf_cross(_args = {})
|
|
369
|
+
0.0
|
|
370
|
+
end
|
|
371
|
+
|
|
372
|
+
def dxf_dim(_args = {})
|
|
373
|
+
0.0
|
|
374
|
+
end
|
|
375
|
+
end
|
|
376
|
+
end
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
# This file is part of SolidRuby.
|
|
2
|
+
#
|
|
3
|
+
# SolidRuby is free software: you can redistribute it and/or modify
|
|
4
|
+
# it under the terms of the GNU General Public License as published by
|
|
5
|
+
# the Free Software Foundation, either version 3 of the License, or
|
|
6
|
+
# (at your option) any later version.
|
|
7
|
+
#
|
|
8
|
+
# SolidRuby is distributed in the hope that it will be useful,
|
|
9
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
10
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
11
|
+
# GNU General Public License for more details.
|
|
12
|
+
#
|
|
13
|
+
# You should have received a copy of the GNU General Public License
|
|
14
|
+
# along with SolidRuby. If not, see <http://www.gnu.org/licenses/>.
|
|
15
|
+
|
|
16
|
+
module SolidRuby::ScrewThreads
|
|
17
|
+
class ScrewThread
|
|
18
|
+
# I would name this Thread but that's already taken by something else
|
|
19
|
+
|
|
20
|
+
attr_accessor :x, :y, :z, :size, :depth, :face
|
|
21
|
+
|
|
22
|
+
def initialize(args = {})
|
|
23
|
+
@x = args[:x] || 0
|
|
24
|
+
@y = args[:y] || 0
|
|
25
|
+
@z = args[:z] || 0
|
|
26
|
+
@depth = args[:depth]
|
|
27
|
+
@size = args[:size]
|
|
28
|
+
@face = args[:face] || :top
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def rotation
|
|
32
|
+
case @face.to_s
|
|
33
|
+
when 'top'
|
|
34
|
+
{}
|
|
35
|
+
when 'bottom'
|
|
36
|
+
{ y: 180 }
|
|
37
|
+
when 'left'
|
|
38
|
+
{ y: -90 }
|
|
39
|
+
when 'right'
|
|
40
|
+
{ y: 90 }
|
|
41
|
+
when 'front' # checkme
|
|
42
|
+
{ x: 90 }
|
|
43
|
+
when 'back'
|
|
44
|
+
{ x: -90 }
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def show
|
|
49
|
+
cylinder(d: @size, h: @depth).rotate(rotation).translate(x: @x, y: @y, z: @z).color(r: 130, g: 130, b: 130)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def output
|
|
53
|
+
show
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def orientation_swap_to(coords, rotation)
|
|
57
|
+
return [coords[0], coords[2], -coords[1]] if rotation[:x].to_i == -90
|
|
58
|
+
return [coords[0], -coords[2], coords[1]] if rotation[:x].to_i == 90
|
|
59
|
+
return [coords[2], coords[1], coords[0]] if rotation[:y].to_i == -90
|
|
60
|
+
return [-coords[2], coords[1], -coords[0]] if rotation[:y].to_i == 90
|
|
61
|
+
|
|
62
|
+
coords
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def position_on(other_thread, rotation = {})
|
|
66
|
+
if other_thread.is_a? Bolt
|
|
67
|
+
# we assume that a bolt is always centered and center the object on
|
|
68
|
+
# the screwthread position
|
|
69
|
+
{ x: -@x, y: -@y, z: -@z }
|
|
70
|
+
else
|
|
71
|
+
# on a screwthread find out its position and orientation
|
|
72
|
+
oc = other_thread.x, other_thread.y, other_thread.z
|
|
73
|
+
oc = orientation_swap_to(oc, rotation)
|
|
74
|
+
{ x: @x - oc[0], y: @y - oc[1], z: @z - oc[2] }
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def create_bolts(face, obj1, obj2, args = {})
|
|
80
|
+
# make a obj1-=obj2 with bolts corresponding to the height of obj1
|
|
81
|
+
|
|
82
|
+
if face.nil? || obj1.nil? || obj2.nil?
|
|
83
|
+
raise 'usage: create_bolts(face,obj1,obj2,args={}) - args can include (obj1.)height and bolt_height'
|
|
84
|
+
return
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# we need to know obj1 height (if not supplied by user)
|
|
88
|
+
#TODO: Rescuing like this is not good practise
|
|
89
|
+
height ||= args[:height]
|
|
90
|
+
case face.to_s
|
|
91
|
+
when 'top'
|
|
92
|
+
height ||= obj1.z rescue nil
|
|
93
|
+
when 'bottom'
|
|
94
|
+
height ||= obj1.z rescue nil
|
|
95
|
+
when 'left'
|
|
96
|
+
height ||= obj1.x rescue nil
|
|
97
|
+
when 'right'
|
|
98
|
+
height ||= obj1.x rescue nil
|
|
99
|
+
when 'front'
|
|
100
|
+
height ||= obj1.y rescue nil
|
|
101
|
+
when 'back'
|
|
102
|
+
height ||= obj1.y rescue nil
|
|
103
|
+
end
|
|
104
|
+
height ||= obj1.height rescue nil
|
|
105
|
+
|
|
106
|
+
if height.nil?
|
|
107
|
+
raise "the object we're substracting from doesn't have a height defined; please define manually"
|
|
108
|
+
return
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
# lets check if the obj2 responds to the threads_[face] method
|
|
112
|
+
|
|
113
|
+
meth = "threads_#{face}"
|
|
114
|
+
|
|
115
|
+
unless obj2.respond_to?(meth)
|
|
116
|
+
raise "The object you're trying to get bolts from doesn't supply any on the face '#{face}'. Please add a method #{meth} to this object"
|
|
117
|
+
return
|
|
118
|
+
end
|
|
119
|
+
holes = obj2.send(meth)
|
|
120
|
+
|
|
121
|
+
return if holes.nil?
|
|
122
|
+
|
|
123
|
+
# let the user either define bolt_heights as integer, array or none (will be guessed)
|
|
124
|
+
if args[:bolt_height].is_a? Array
|
|
125
|
+
bolt_heights = args[:bolt_height]
|
|
126
|
+
if bolt_heights.size != holes.size
|
|
127
|
+
raise "object has #{holes.size} threads for bolts but you supplied #{bolt_heights.size}"
|
|
128
|
+
return
|
|
129
|
+
end
|
|
130
|
+
else
|
|
131
|
+
bolt_heights = []
|
|
132
|
+
holes.each do |hole|
|
|
133
|
+
bolt_heights << if args[:bolt_height]
|
|
134
|
+
args[:bolt_height]
|
|
135
|
+
else
|
|
136
|
+
(height + hole.depth).floor
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
ret = []
|
|
142
|
+
holes.each_with_index do |hole, i|
|
|
143
|
+
bolt = Bolt.new(hole.size, bolt_heights[i], washer: args[:washer])
|
|
144
|
+
case face
|
|
145
|
+
when 'top'
|
|
146
|
+
bolt.transformations << Rotate.new(x: 180)
|
|
147
|
+
bolt.transformations << Translate.new(x: hole.x, y: hole.y, z: hole.z + height)
|
|
148
|
+
when 'bottom'
|
|
149
|
+
bolt.transformations << Translate.new(x: hole.x, y: hole.y, z: hole.z)
|
|
150
|
+
when 'left'
|
|
151
|
+
bolt.transformations << Rotate.new(y: 90)
|
|
152
|
+
bolt.transformations << Translate.new(x: hole.x, y: hole.y, z: hole.z)
|
|
153
|
+
when 'right'
|
|
154
|
+
bolt.transformations << Rotate.new(y: -90)
|
|
155
|
+
bolt.transformations << Translate.new(x: hole.x + height, y: hole.y, z: hole.z)
|
|
156
|
+
when 'front'
|
|
157
|
+
bolt.transformations << Rotate.new(x: -90)
|
|
158
|
+
bolt.transformations << Translate.new(x: hole.x, y: hole.y, z: hole.z)
|
|
159
|
+
when 'back'
|
|
160
|
+
bolt.transformations << Rotate.new(x: 90)
|
|
161
|
+
bolt.transformations << Translate.new(x: hole.x, y: hole.y + height, z: hole.z)
|
|
162
|
+
end
|
|
163
|
+
bolt.transformations += obj2.transformations unless obj2.transformations.nil?
|
|
164
|
+
|
|
165
|
+
ret << bolt
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
ret
|
|
169
|
+
end
|
|
170
|
+
end
|