scad-btw 0.1.0.pre1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.rspec +3 -0
- data/.rubocop.yml +17 -0
- data/.ruby-version +1 -0
- data/CODE_OF_CONDUCT.md +84 -0
- data/Gemfile +13 -0
- data/LICENSE.txt +21 -0
- data/README.md +31 -0
- data/Rakefile +12 -0
- data/exe/scad-btw +6 -0
- data/flake.lock +306 -0
- data/flake.nix +63 -0
- data/lib/extensions/jenncad.rb +91 -0
- data/lib/extensions/kernel.rb +17 -0
- data/lib/extensions/thor.rb +11 -0
- data/lib/scad/btw/base.rb +224 -0
- data/lib/scad/btw/cli/base.rb +31 -0
- data/lib/scad/btw/cli/concerns/export_formats.rb +43 -0
- data/lib/scad/btw/cli/concerns/export_options.rb +62 -0
- data/lib/scad/btw/cli/presets.rb +66 -0
- data/lib/scad/btw/cli/solid.rb +33 -0
- data/lib/scad/btw/cli/spoked.rb +33 -0
- data/lib/scad/btw/component/axle_hole.rb +53 -0
- data/lib/scad/btw/component/center.rb +58 -0
- data/lib/scad/btw/component/counterweight.rb +117 -0
- data/lib/scad/btw/component/flange.rb +96 -0
- data/lib/scad/btw/component/joint.rb +57 -0
- data/lib/scad/btw/component/joint_base.rb +34 -0
- data/lib/scad/btw/component/o_ring_groove.rb +95 -0
- data/lib/scad/btw/component/solid.rb +67 -0
- data/lib/scad/btw/component/spokes.rb +118 -0
- data/lib/scad/btw/component/tread.rb +109 -0
- data/lib/scad/btw/concerns/component_args.rb +26 -0
- data/lib/scad/btw/concerns/flange_heights.rb +24 -0
- data/lib/scad/btw/concerns/joint_args.rb +58 -0
- data/lib/scad/btw/concerns/part_commons.rb +29 -0
- data/lib/scad/btw/concerns/tread_width.rb +21 -0
- data/lib/scad/btw/converters/openscad_2_ascii_stl.rb +39 -0
- data/lib/scad/btw/presets/scale_1_38/cargo_wheel_thin_36_inch.rb +21 -0
- data/lib/scad/btw/presets/scale_1_38/v20.rb +83 -0
- data/lib/scad/btw/solid.rb +13 -0
- data/lib/scad/btw/spoked.rb +13 -0
- data/lib/scad/btw/version.rb +7 -0
- data/lib/scad/btw.rb +29 -0
- data/sig/scad/btw.rbs +6 -0
- metadata +150 -0
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'extensions/jenncad'
|
4
|
+
|
5
|
+
module Extensions
|
6
|
+
module Kernel
|
7
|
+
def require(path)
|
8
|
+
ret = super
|
9
|
+
|
10
|
+
if path == 'jenncad/profile_loader'
|
11
|
+
::JennCad::ProfileLoader.prepend Extensions::JennCad::ProfileLoader
|
12
|
+
end
|
13
|
+
|
14
|
+
ret
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,224 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'scad/btw/concerns/component_args'
|
4
|
+
require 'scad/btw/concerns/part_commons'
|
5
|
+
|
6
|
+
require 'scad/btw/component/axle_hole'
|
7
|
+
require 'scad/btw/component/center'
|
8
|
+
require 'scad/btw/component/counterweight'
|
9
|
+
require 'scad/btw/component/flange'
|
10
|
+
require 'scad/btw/component/joint_base'
|
11
|
+
require 'scad/btw/component/joint'
|
12
|
+
require 'scad/btw/component/o_ring_groove'
|
13
|
+
require 'scad/btw/component/solid'
|
14
|
+
require 'scad/btw/component/spokes'
|
15
|
+
require 'scad/btw/component/tread'
|
16
|
+
|
17
|
+
module Scad
|
18
|
+
module Btw
|
19
|
+
class Base < JennCad::Part
|
20
|
+
include Scad::Btw::Concerns::PartCommons
|
21
|
+
|
22
|
+
# Wheel size mapping
|
23
|
+
# See eurobricks.com forum post https://bit.ly/3ZARZUZ for details
|
24
|
+
OLD_2_NEW_SIZE_MAP = {
|
25
|
+
'XXL' => 13,
|
26
|
+
'XLL' => 12,
|
27
|
+
'XL' => 11,
|
28
|
+
'LL' => 10,
|
29
|
+
'L' => 9,
|
30
|
+
'ML' => 8,
|
31
|
+
'M' => 7,
|
32
|
+
'MS' => 6,
|
33
|
+
'S' => 5
|
34
|
+
}.freeze
|
35
|
+
|
36
|
+
DEFAULTS = {
|
37
|
+
COLOR: :gray,
|
38
|
+
HEIGHT: 8,
|
39
|
+
INNER_HEIGHT_DIFF: -0.5,
|
40
|
+
IS_BLIND: false,
|
41
|
+
IS_THIN: true,
|
42
|
+
THIN_HEIGHT: 5,
|
43
|
+
WITH_COUNTERWEIGHT: false,
|
44
|
+
WITH_JOINT: false,
|
45
|
+
WITH_O_RING_GROOVE: false
|
46
|
+
}.freeze
|
47
|
+
|
48
|
+
COMPONENT_ARGS_MAPPING = {
|
49
|
+
axle: { height: :height },
|
50
|
+
center: { height: :height },
|
51
|
+
counterweight: { height: :inner_height, diameter: :size_2_diameter },
|
52
|
+
flange: { diameter: :size_2_diameter },
|
53
|
+
joint: { height: :height },
|
54
|
+
o_ring_groove: { diameter: :size_2_diameter, thin: :thin? },
|
55
|
+
solid: { height: :inner_height, diameter: :size_2_diameter },
|
56
|
+
spokes: { height: :inner_height, diameter: :size_2_diameter },
|
57
|
+
tread: { diameter: :size_2_diameter, height: :height }
|
58
|
+
}.freeze
|
59
|
+
|
60
|
+
ARGS = {
|
61
|
+
prefix: :wheel,
|
62
|
+
args: {
|
63
|
+
size: {
|
64
|
+
description: 'Wheel size.', required: true, type: :string,
|
65
|
+
enum: OLD_2_NEW_SIZE_MAP.keys + OLD_2_NEW_SIZE_MAP.values.map(&:to_s)
|
66
|
+
},
|
67
|
+
is_thin: {
|
68
|
+
description: 'Whether wheel is thin (5 mm) or not (8 mm).', default: DEFAULTS[:IS_THIN], type: :boolean
|
69
|
+
},
|
70
|
+
inner_height: {
|
71
|
+
description: "Height of spokes or web. Defaults to: Wheel thickness #{DEFAULTS[:INNER_HEIGHT_DIFF]}",
|
72
|
+
type: :numeric
|
73
|
+
},
|
74
|
+
with_o_ring_groove: {
|
75
|
+
description: 'Whether wheel has o-ring groove.', default: DEFAULTS[:WITH_O_RING_GROOVE], type: :boolean
|
76
|
+
},
|
77
|
+
with_joint: {
|
78
|
+
description: 'Whether wheel has joint.', default: DEFAULTS[:WITH_JOINT], type: :boolean
|
79
|
+
},
|
80
|
+
with_counterweight: {
|
81
|
+
description: 'Whether wheel has counterweight.', default: DEFAULTS[:WITH_COUNTERWEIGHT], type: :boolean
|
82
|
+
}
|
83
|
+
}
|
84
|
+
}.freeze
|
85
|
+
|
86
|
+
def initialize(args = {})
|
87
|
+
args = {}.merge(args.transform_keys(&:to_sym))
|
88
|
+
|
89
|
+
super(args)
|
90
|
+
|
91
|
+
@args = args
|
92
|
+
end
|
93
|
+
|
94
|
+
def part
|
95
|
+
(parts_additions - parts_substractions).color(color)
|
96
|
+
end
|
97
|
+
|
98
|
+
def self.component_classes
|
99
|
+
Scad::Btw::Component.constants.map(&Scad::Btw::Component.method(:const_get)).select { |c| c.is_a? Class }
|
100
|
+
end
|
101
|
+
|
102
|
+
def self.skip_components
|
103
|
+
[]
|
104
|
+
end
|
105
|
+
|
106
|
+
private
|
107
|
+
|
108
|
+
attr_reader :args
|
109
|
+
|
110
|
+
def skip_components
|
111
|
+
self.class.skip_components
|
112
|
+
end
|
113
|
+
|
114
|
+
def parts_additions
|
115
|
+
res = nil
|
116
|
+
|
117
|
+
component_classes.each do |c|
|
118
|
+
next if skip_component?(c, :addition)
|
119
|
+
|
120
|
+
res ? res += component_part(c) : res = component_part(c)
|
121
|
+
end
|
122
|
+
|
123
|
+
res
|
124
|
+
end
|
125
|
+
|
126
|
+
def parts_substractions
|
127
|
+
res = nil
|
128
|
+
|
129
|
+
component_classes.each do |c|
|
130
|
+
next if skip_component?(c, :substraction)
|
131
|
+
|
132
|
+
res ? res += component_part(c) : res = component_part(c)
|
133
|
+
end
|
134
|
+
|
135
|
+
res
|
136
|
+
end
|
137
|
+
|
138
|
+
# components
|
139
|
+
|
140
|
+
def component_part(component_class)
|
141
|
+
component_class.new(component_args(component_class)).part
|
142
|
+
end
|
143
|
+
|
144
|
+
def component_args(component_class)
|
145
|
+
component_global_args(component_class).merge(component_class.component_args(args)).merge(misc_args)
|
146
|
+
end
|
147
|
+
|
148
|
+
def component_global_args(component_class)
|
149
|
+
prefix = component_class::ARGS[:prefix]
|
150
|
+
|
151
|
+
COMPONENT_ARGS_MAPPING[prefix].transform_values { |v| send(v) }
|
152
|
+
end
|
153
|
+
|
154
|
+
def skip_component?(component_class, type)
|
155
|
+
return true unless type == component_class::TYPE
|
156
|
+
return true if skip_components.include?(component_class::ARGS[:prefix])
|
157
|
+
return true if not_with?(component_class::ARGS[:prefix])
|
158
|
+
|
159
|
+
false
|
160
|
+
end
|
161
|
+
|
162
|
+
def not_with?(component)
|
163
|
+
return false unless %i[counterweight joint o_ring_groove].include?(component)
|
164
|
+
|
165
|
+
!send("with_#{component}?".to_sym)
|
166
|
+
end
|
167
|
+
|
168
|
+
def component_classes
|
169
|
+
self.class.component_classes
|
170
|
+
end
|
171
|
+
|
172
|
+
# functions
|
173
|
+
|
174
|
+
def misc_args
|
175
|
+
args.except do |key, _|
|
176
|
+
component_classes.join(self.class).map { |c| c.component_args_key_map.values }.flatten.include?(key)
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
def height
|
181
|
+
thin? ? DEFAULTS[:THIN_HEIGHT] : DEFAULTS[:HEIGHT]
|
182
|
+
end
|
183
|
+
|
184
|
+
def thin?
|
185
|
+
args.fetch(:wheel_is_thin, DEFAULTS[:IS_THIN])
|
186
|
+
end
|
187
|
+
|
188
|
+
def inner_height
|
189
|
+
args[:wheel_inner_height] || (height + DEFAULTS[:INNER_HEIGHT_DIFF])
|
190
|
+
end
|
191
|
+
|
192
|
+
# See eurobricks.com forum post https://bit.ly/3ZARZUZ for details
|
193
|
+
def size_2_diameter
|
194
|
+
(size + 0.5) * 3.2
|
195
|
+
end
|
196
|
+
|
197
|
+
def size
|
198
|
+
provided_size = args.fetch(:wheel_size)
|
199
|
+
|
200
|
+
mapped_size = OLD_2_NEW_SIZE_MAP[provided_size] || provided_size
|
201
|
+
|
202
|
+
raise "Size #{provided_size} not supportet!" unless OLD_2_NEW_SIZE_MAP.values.include?(mapped_size.to_i)
|
203
|
+
|
204
|
+
mapped_size.to_f
|
205
|
+
end
|
206
|
+
|
207
|
+
def color
|
208
|
+
args[:wheel_color] || DEFAULTS[:COLOR]
|
209
|
+
end
|
210
|
+
|
211
|
+
def with_counterweight?
|
212
|
+
args[:wheel_with_counterweight] || with_joint? || DEFAULTS[:WITH_COUNTERWEIGHT]
|
213
|
+
end
|
214
|
+
|
215
|
+
def with_o_ring_groove?
|
216
|
+
args[:wheel_with_o_ring_groove] || DEFAULTS[:WITH_O_RING_GROOVE]
|
217
|
+
end
|
218
|
+
|
219
|
+
def with_joint?
|
220
|
+
args[:wheel_with_joint] || DEFAULTS[:WITH_JOINT]
|
221
|
+
end
|
222
|
+
end
|
223
|
+
end
|
224
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'thor'
|
4
|
+
require 'extensions/thor'
|
5
|
+
Thor::Option.prepend Extensions::Thor::Option
|
6
|
+
|
7
|
+
require 'scad/btw'
|
8
|
+
require_relative 'presets'
|
9
|
+
require_relative 'solid'
|
10
|
+
require_relative 'spoked'
|
11
|
+
|
12
|
+
module Scad
|
13
|
+
module Btw
|
14
|
+
module Cli
|
15
|
+
class Base < Thor
|
16
|
+
desc 'preset SUBCOMMAND ...ARGS', 'Generate from presets'
|
17
|
+
subcommand 'preset', Scad::Btw::Cli::Presets
|
18
|
+
|
19
|
+
desc 'solid SUBCOMMAND ...ARGS', 'Generate solid wheel'
|
20
|
+
subcommand 'solid', Scad::Btw::Cli::Solid
|
21
|
+
|
22
|
+
desc 'spoked SUBCOMMAND ...ARGS', 'Generate spoked wheel'
|
23
|
+
subcommand 'spoked', Scad::Btw::Cli::Spoked
|
24
|
+
|
25
|
+
def self.exit_on_failure?
|
26
|
+
true
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'tempfile'
|
4
|
+
|
5
|
+
module Scad
|
6
|
+
module Btw
|
7
|
+
module Cli
|
8
|
+
module Concerns
|
9
|
+
module ExportFormats
|
10
|
+
extend ActiveSupport::Concern
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def export_part(part, file, format = 'scad')
|
15
|
+
case format
|
16
|
+
when 'scad'
|
17
|
+
export_part_to_scad(part, file)
|
18
|
+
when 'stl'
|
19
|
+
export_stl(part, file)
|
20
|
+
else
|
21
|
+
puts "Unknown export format `#{format}`. Choose one of `scad` and `stl`."
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def export_part_to_scad(part, file)
|
26
|
+
JennCad::Exporters::OpenScad.new(part).save(file)
|
27
|
+
end
|
28
|
+
|
29
|
+
def export_stl(part, file)
|
30
|
+
tempfile = Tempfile.new('scad')
|
31
|
+
|
32
|
+
export_part_to_scad(part, tempfile.path)
|
33
|
+
|
34
|
+
Scad::Btw::Converters::Openscad2AsciiStl.convert(in_path: tempfile.path, out_path: file)
|
35
|
+
ensure
|
36
|
+
tempfile.close
|
37
|
+
tempfile.unlink
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Scad
|
4
|
+
module Btw
|
5
|
+
module Cli
|
6
|
+
module Concerns
|
7
|
+
module ExportOptions
|
8
|
+
extend ActiveSupport::Concern
|
9
|
+
|
10
|
+
class_methods do
|
11
|
+
def _gen_options
|
12
|
+
_wheel_options + _component_options
|
13
|
+
end
|
14
|
+
|
15
|
+
def _wheel_options
|
16
|
+
_part_options(klass: Object.const_get(self::WHEEL_CLASS_NAME))
|
17
|
+
end
|
18
|
+
|
19
|
+
def _part_options(klass:)
|
20
|
+
klass::ARGS[:args].keys.map do |key|
|
21
|
+
_option_args(
|
22
|
+
prefix: klass::ARGS[:prefix],
|
23
|
+
name: key,
|
24
|
+
arg: klass::ARGS[:args][key]
|
25
|
+
)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def _component_options
|
30
|
+
Object.const_get(self::WHEEL_CLASS_NAME).component_classes
|
31
|
+
.map do |cc|
|
32
|
+
_component_option(klass: cc)
|
33
|
+
end.flatten
|
34
|
+
end
|
35
|
+
|
36
|
+
def _component_option(klass:)
|
37
|
+
if Object.const_get(self::WHEEL_CLASS_NAME).skip_components
|
38
|
+
.include?(klass::ARGS[:prefix])
|
39
|
+
[]
|
40
|
+
else
|
41
|
+
_part_options(klass: klass)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def _option_args(prefix:, name:, arg:)
|
46
|
+
args = {
|
47
|
+
name: "#{prefix}_#{name}".to_sym,
|
48
|
+
kwargs: { desc: arg[:description] }
|
49
|
+
}
|
50
|
+
|
51
|
+
%i[type default required enum hide].each do |option|
|
52
|
+
args[:kwargs][option] = arg[option] if arg.key?(option)
|
53
|
+
end
|
54
|
+
|
55
|
+
args
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'thor'
|
4
|
+
require 'scad/btw/cli/concerns/export_formats'
|
5
|
+
|
6
|
+
module Scad
|
7
|
+
module Btw
|
8
|
+
module Cli
|
9
|
+
class Presets < Thor
|
10
|
+
include ActiveSupport::Inflector
|
11
|
+
include Scad::Btw::Cli::Concerns::ExportFormats
|
12
|
+
|
13
|
+
PRESETS_NAMESPACE = 'Scad::Btw::Presets'
|
14
|
+
|
15
|
+
desc 'list', 'List available presets'
|
16
|
+
def list
|
17
|
+
print list_output
|
18
|
+
end
|
19
|
+
|
20
|
+
option :preset, required: true, type: :string
|
21
|
+
desc 'export FILE [FORMAT]', 'Export preset to file in either `scad` (default) or `stl` format'
|
22
|
+
def export(file, format = 'scad')
|
23
|
+
export_part(part, file, format)
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def part
|
29
|
+
preset_class_name = "#{PRESETS_NAMESPACE}::#{camelize(underscore(options[:preset]))}"
|
30
|
+
|
31
|
+
constantize(preset_class_name).to_openscad
|
32
|
+
end
|
33
|
+
|
34
|
+
def list_output
|
35
|
+
<<~LIST_OUTPUT
|
36
|
+
Available presets:
|
37
|
+
|
38
|
+
#{presets.map { |p| " - #{p}" }.join("\n")}
|
39
|
+
|
40
|
+
Use `scad-btw preset export --preset <preset> <file>` to export a
|
41
|
+
preset to openscad.
|
42
|
+
LIST_OUTPUT
|
43
|
+
end
|
44
|
+
|
45
|
+
def presets
|
46
|
+
get_classes(constantize(PRESETS_NAMESPACE)).map do |c|
|
47
|
+
dasherize(underscore(c.name.delete_prefix("#{PRESETS_NAMESPACE}::")))
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def get_classes(mod)
|
52
|
+
mod.constants.map do |c|
|
53
|
+
const = mod.const_get(c)
|
54
|
+
if const.is_a? Class
|
55
|
+
const
|
56
|
+
elsif const.is_a? Module
|
57
|
+
get_classes(const)
|
58
|
+
else
|
59
|
+
next
|
60
|
+
end
|
61
|
+
end.flatten
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'thor'
|
4
|
+
require 'scad/btw/cli/concerns/export_options'
|
5
|
+
require 'scad/btw/cli/concerns/export_formats'
|
6
|
+
|
7
|
+
module Scad
|
8
|
+
module Btw
|
9
|
+
module Cli
|
10
|
+
class Solid < Thor
|
11
|
+
include Scad::Btw::Cli::Concerns::ExportOptions
|
12
|
+
include Scad::Btw::Cli::Concerns::ExportFormats
|
13
|
+
include ActiveSupport::Inflector
|
14
|
+
|
15
|
+
WHEEL_CLASS_NAME = 'Scad::Btw::Solid'
|
16
|
+
|
17
|
+
_gen_options.each do |conf|
|
18
|
+
option(conf[:name], conf[:kwargs])
|
19
|
+
end
|
20
|
+
desc 'export FILE [FORMAT]', 'Export solid wheel to file in either `scad` (default) or `stl` format'
|
21
|
+
def export(file, format = 'scad')
|
22
|
+
export_part(part, file, format)
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def part
|
28
|
+
constantize(WHEEL_CLASS_NAME).to_openscad(options)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'thor'
|
4
|
+
require 'scad/btw/cli/concerns/export_options'
|
5
|
+
require 'scad/btw/cli/concerns/export_formats'
|
6
|
+
|
7
|
+
module Scad
|
8
|
+
module Btw
|
9
|
+
module Cli
|
10
|
+
class Spoked < Thor
|
11
|
+
include Scad::Btw::Cli::Concerns::ExportOptions
|
12
|
+
include Scad::Btw::Cli::Concerns::ExportFormats
|
13
|
+
include ActiveSupport::Inflector
|
14
|
+
|
15
|
+
WHEEL_CLASS_NAME = 'Scad::Btw::Spoked'
|
16
|
+
|
17
|
+
_gen_options.each do |conf|
|
18
|
+
option(conf[:name], conf[:kwargs])
|
19
|
+
end
|
20
|
+
desc 'export FILE [FORMAT]', 'Export solid wheel to file in either `scad` (default) or `stl` format'
|
21
|
+
def export(file, format = 'scad')
|
22
|
+
export_part(part, file, format)
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def part
|
28
|
+
constantize(WHEEL_CLASS_NAME).to_openscad(options)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'scad/btw/concerns/component_args'
|
4
|
+
require 'scad/btw/concerns/part_commons'
|
5
|
+
|
6
|
+
module Scad
|
7
|
+
module Btw
|
8
|
+
module Component
|
9
|
+
class AxleHole < JennCad::Part
|
10
|
+
include Scad::Btw::Concerns::PartCommons
|
11
|
+
include Scad::Btw::Concerns::ComponentArgs
|
12
|
+
|
13
|
+
TYPE = :substraction
|
14
|
+
SPLINE_WIDTH = 2
|
15
|
+
DIAMETER = 5
|
16
|
+
|
17
|
+
ARGS = {
|
18
|
+
prefix: :axle,
|
19
|
+
args: {
|
20
|
+
height: {
|
21
|
+
description: 'Wheel height. Defaults to: Wheel height defined ' \
|
22
|
+
'by wheel thickness (`wheel_is_thin` flag).',
|
23
|
+
type: :numeric,
|
24
|
+
hide: true
|
25
|
+
}
|
26
|
+
}
|
27
|
+
}.freeze
|
28
|
+
|
29
|
+
def initialize(args = {})
|
30
|
+
super
|
31
|
+
|
32
|
+
@height = args.fetch(:height)
|
33
|
+
end
|
34
|
+
|
35
|
+
def part
|
36
|
+
res = spline
|
37
|
+
|
38
|
+
res + spline.rz(90)
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
attr_reader :height
|
44
|
+
|
45
|
+
# components
|
46
|
+
|
47
|
+
def spline
|
48
|
+
cube(x: DIAMETER, y: SPLINE_WIDTH, z: height + 1).mz(-0.5)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'scad/btw/concerns/component_args'
|
4
|
+
require 'scad/btw/concerns/part_commons'
|
5
|
+
|
6
|
+
module Scad
|
7
|
+
module Btw
|
8
|
+
module Component
|
9
|
+
class Center < JennCad::Part
|
10
|
+
include Scad::Btw::Concerns::PartCommons
|
11
|
+
include Scad::Btw::Concerns::ComponentArgs
|
12
|
+
|
13
|
+
TYPE = :addition
|
14
|
+
MIN_DIAMETER = 7.4
|
15
|
+
|
16
|
+
ARGS = {
|
17
|
+
prefix: :center,
|
18
|
+
args: {
|
19
|
+
height: {
|
20
|
+
description: 'Center height. Defaults to: Wheel height defined ' \
|
21
|
+
'by wheel thickness (`wheel_is_thin` flag).',
|
22
|
+
type: :numeric,
|
23
|
+
hide: true
|
24
|
+
},
|
25
|
+
diameter: {
|
26
|
+
description: 'Center diameter. Minimum diameter of ' \
|
27
|
+
"#{MIN_DIAMETER} will be used if provided value " \
|
28
|
+
'is smaller.',
|
29
|
+
default: MIN_DIAMETER,
|
30
|
+
type: :numeric
|
31
|
+
}
|
32
|
+
}
|
33
|
+
}.freeze
|
34
|
+
|
35
|
+
def initialize(args = {})
|
36
|
+
super
|
37
|
+
|
38
|
+
@diameter = args[:diameter] || 0
|
39
|
+
@height = args.fetch(:height)
|
40
|
+
end
|
41
|
+
|
42
|
+
def part
|
43
|
+
cylinder(d: calculated_diameter, h: height)
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
attr_reader :diameter, :height
|
49
|
+
|
50
|
+
# functions
|
51
|
+
|
52
|
+
def calculated_diameter
|
53
|
+
[diameter, MIN_DIAMETER].max
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|