crystalscad 0.3.7 → 0.3.8

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,45 @@
1
+ #!/usr/bin/ruby1.9.3
2
+ require "rubygems"
3
+ require "crystalscad"
4
+ include CrystalScad
5
+
6
+ size=50
7
+ hole=25
8
+ h = size * 2.5
9
+
10
+ res = sphere(d:size)
11
+ res -= cylinder(d:hole,h:h,center:true)
12
+ res -= cylinder(d:hole,h:h,center:true).rotate(x:90)
13
+ res -= cylinder(d:hole,h:h,center:true).rotate(y:90)
14
+
15
+ res.save("example001.scad")
16
+
17
+
18
+
19
+ =begin
20
+ module example001()
21
+ {
22
+ function r_from_dia(d) = d / 2;
23
+
24
+ module rotcy(rot, r, h) {
25
+ rotate(90, rot)
26
+ cylinder(r = r, h = h, center = true);
27
+ }
28
+
29
+ difference() {
30
+ sphere(r = r_from_dia(size));
31
+ rotcy([0, 0, 0], cy_r, cy_h);
32
+ rotcy([1, 0, 0], cy_r, cy_h);
33
+ rotcy([0, 1, 0], cy_r, cy_h);
34
+ }
35
+
36
+ size = 50;
37
+ hole = 25;
38
+
39
+ cy_r = r_from_dia(hole);
40
+ cy_h = r_from_dia(size * 2.5);
41
+ }
42
+
43
+ example001();
44
+ =end
45
+
@@ -0,0 +1,51 @@
1
+ #!/usr/bin/ruby1.9.3
2
+ require "rubygems"
3
+ require "crystalscad"
4
+ include CrystalScad
5
+
6
+ # note that center:true doesn't work with cube
7
+ # however, there are convenience methods like
8
+ # center, center_x, center_y, center_xy, center_z available.
9
+ # As rule of thumb, avoid center if possible.
10
+
11
+ res1 = cube([30,30,30]).center
12
+ res1+= cube([15,15,50]).center.translate(z:-25)
13
+
14
+ res2 = cube([50,10,10]).center
15
+ res2+= cube([10,50,10]).center
16
+ res2+= cube([10,10,50]).center
17
+
18
+ res = res1-res2
19
+ res*=cylinder(r1:20,r2:5,h:50,center:true).translate(z:5)
20
+
21
+ res.save("example002.scad")
22
+
23
+
24
+
25
+
26
+
27
+ =begin
28
+ module example002()
29
+ {
30
+ intersection() {
31
+ difference() {
32
+ union() {
33
+ cube([30, 30, 30], center = true);
34
+ translate([0, 0, -25])
35
+ cube([15, 15, 50], center = true);
36
+ }
37
+ union() {
38
+ cube([50, 10, 10], center = true);
39
+ cube([10, 50, 10], center = true);
40
+ cube([10, 10, 50], center = true);
41
+ }
42
+ }
43
+ translate([0, 0, 5])
44
+ cylinder(h = 50, r1 = 20, r2 = 5, center = true);
45
+ }
46
+ }
47
+
48
+ example002();
49
+ =end
50
+
51
+
@@ -0,0 +1,42 @@
1
+ #!/usr/bin/ruby1.9.3
2
+ require "rubygems"
3
+ require "crystalscad"
4
+ include CrystalScad
5
+
6
+
7
+ def example003
8
+ res1 = cube([30,30,30]).center
9
+ res2 = nil # either initialize it with a CrystalScadObject or nil as we do a += on it later on
10
+ [[1,0,0],[0,1,0],[0,0,1]].each do |x,y,z|
11
+ res1+= cube([15+x*25,15+y*25,15+z*25]).center
12
+ res2+= cube([10+x*40,10+y*40,+10+z*40]).center
13
+ end
14
+ res1-res2
15
+ end
16
+
17
+ example003.save("example003.scad")
18
+
19
+
20
+ =begin
21
+
22
+ module example003()
23
+ {
24
+ difference() {
25
+ union() {
26
+ cube([30, 30, 30], center = true);
27
+ cube([40, 15, 15], center = true);
28
+ cube([15, 40, 15], center = true);
29
+ cube([15, 15, 40], center = true);
30
+ }
31
+ union() {
32
+ cube([50, 10, 10], center = true);
33
+ cube([10, 50, 10], center = true);
34
+ cube([10, 10, 50], center = true);
35
+ }
36
+ }
37
+ }
38
+
39
+ example003();
40
+
41
+ =end
42
+
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/ruby1.9.3
2
+ require "rubygems"
3
+ require "crystalscad"
4
+ include CrystalScad
5
+
6
+
7
+ def example004
8
+ cube([30,30,30]).center-sphere(d:40)
9
+ end
10
+
11
+ example004.save("example004.scad")
12
+
13
+
14
+ =begin
15
+
16
+
17
+ module example004()
18
+ {
19
+ difference() {
20
+ cube(30, center = true);
21
+ sphere(20);
22
+ }
23
+ }
24
+
25
+ example004();
26
+
27
+
28
+ =end
29
+
@@ -0,0 +1,58 @@
1
+ #!/usr/bin/ruby1.9.3
2
+ require "rubygems"
3
+ require "crystalscad"
4
+ include CrystalScad
5
+
6
+
7
+ # note that openscad works with radians automatically and ruby doesn't.
8
+ def radians(a)
9
+ a/180.0 * Math::PI
10
+ end
11
+
12
+ def example005
13
+ # base
14
+ res = cylinder(d:200,h:50)
15
+ res -= cylinder(d:160,h:50).translate(z:10)
16
+ res -= cube([50,50,50]).center.translate(x:100,z:35)
17
+
18
+ # pylons
19
+ (0..5).each do |i|
20
+ res+= cylinder(d:20,h:200).translate(x:Math::sin(radians(360*i/6))*80,y:Math::cos(radians(360*i/6))*80)
21
+ end
22
+
23
+ # roof
24
+ res += cylinder(d1:240,d2:0,h:80).translate(z:200)
25
+
26
+ res.translate(z:-120)
27
+ end
28
+
29
+ example005.save("example005.scad")
30
+
31
+
32
+ =begin
33
+
34
+
35
+
36
+ module example005()
37
+ {
38
+ translate([0, 0, -120]) {
39
+ difference() {
40
+ cylinder(h = 50, r = 100);
41
+ translate([0, 0, 10]) cylinder(h = 50, r = 80);
42
+ translate([100, 0, 35]) cube(50, center = true);
43
+ }
44
+ for (i = [0:5]) {
45
+ echo(360*i/6, sin(360*i/6)*80, cos(360*i/6)*80);
46
+ translate([sin(360*i/6)*80, cos(360*i/6)*80, 0 ])
47
+ cylinder(h = 200, r=10);
48
+ }
49
+ translate([0, 0, 200])
50
+ cylinder(h = 80, r1 = 120, r2 = 0);
51
+ }
52
+ }
53
+
54
+ example005();
55
+
56
+
57
+ =end
58
+
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/ruby1.9.3
2
+ require "rubygems"
3
+ require "crystalscad"
4
+ include CrystalScad
5
+
6
+
7
+ g1 = PrintedGear.new(module:2.0,teeth:40,bore:5,height:4)
8
+ g2 = PrintedGear.new(module:2.0,teeth:20,bore:5,height:4,rotation:0.5) # rotation in number of teeth
9
+
10
+ res = g1.show.color("red").rotate(z:"$t*360")
11
+ res += g2.show.rotate(z:"-$t*360*#{g1.ratio(g2)}").translate(x:g1.distance_to(g2))
12
+
13
+ res.save("printed_gear.scad")
14
+
@@ -0,0 +1,102 @@
1
+ #!/usr/bin/ruby1.9.3
2
+ require "rubygems"
3
+ require "crystalscad"
4
+ include CrystalScad
5
+
6
+ # This example shows the use of ScrewThreads in CrystalScad.
7
+
8
+ class CustomPartWithFemaleThread < CrystalScad::Assembly
9
+ # this could be something like a tslot-nut
10
+
11
+ def initialize
12
+ @x=8
13
+ @y=20
14
+ @z=8
15
+ end
16
+
17
+ def show
18
+ res = cube([@x,@y,@z]).color(r:180,b:180,g:180)
19
+ res -= threads_top.map(&:show) # - tries output normally, we want show here
20
+ end
21
+
22
+ def threads_top
23
+ holes =*ScrewThread.new(x:@x/2,y:@y/2+3,size:4,depth:@z)
24
+ end
25
+
26
+ end
27
+
28
+
29
+ class CustomPartWithMaleThread < CrystalScad::Assembly
30
+ def initialize
31
+ @x=50
32
+ @y=50
33
+ @z=15
34
+ end
35
+
36
+ def show
37
+ res = cube([@x,@y,@z]).color(r:200,b:200,g:200,a:100)
38
+ res += threads
39
+
40
+ end
41
+
42
+ def threads_top
43
+ holes =*ScrewThread.new(x:@x/2+2,y:@y/2+2,z:@z,size:4,depth:@z)
44
+ end
45
+
46
+ def threads_bottom
47
+ holes =*ScrewThread.new(x:@x/2+2,y:@y/2+2,z:0,size:4,depth:@z,face:"bottom")
48
+ end
49
+
50
+ def threads_left
51
+ holes =*ScrewThread.new(x:0,y:10,z:8,size:4,depth:10,face:"left")
52
+ end
53
+
54
+ def threads_right
55
+ holes =*ScrewThread.new(x:@x,y:15,z:3,size:4,depth:10,face:"right")
56
+ end
57
+
58
+ def threads_front
59
+ holes =*ScrewThread.new(x:25,y:0,z:11,size:4,depth:10,face:"front")
60
+ end
61
+
62
+ def threads_back
63
+ holes =*ScrewThread.new(x:25,y:@y,z:11,size:4,depth:10,face:"back")
64
+ end
65
+
66
+ end
67
+
68
+
69
+ female=CustomPartWithFemaleThread.new
70
+ male =CustomPartWithMaleThread.new
71
+
72
+ pos = male.threads_top.first.position_on(female.threads_top.first)
73
+
74
+ res = male.show
75
+ res += female.show.translate(pos)
76
+
77
+ rotation = {}
78
+ pos = male.threads_bottom.first.position_on(female.threads_top.first,rotation)
79
+ res += female.show.rotate(rotation).mirror(z:1).translate(pos)
80
+
81
+
82
+ rotation = {y:-90}
83
+ pos = male.threads_left.first.position_on(female.threads_top.first,rotation)
84
+ res += female.show.rotate(rotation).translate(pos)
85
+
86
+ rotation = {y:90}
87
+ pos = male.threads_right.first.position_on(female.threads_top.first,rotation)
88
+ res += female.show.rotate(rotation).translate(pos)
89
+
90
+
91
+ rotation = {x:90}
92
+ pos = male.threads_front.first.position_on(female.threads_top.first,rotation)
93
+ # testing rotate_around here
94
+ res += female.show.rotate_around(female.threads_top.first,z:90).rotate(rotation).translate(pos)
95
+
96
+
97
+ rotation = {x:-90}
98
+ pos = male.threads_back.first.position_on(female.threads_top.first,rotation)
99
+ res += female.show.rotate(rotation).translate(pos)
100
+
101
+
102
+ res.save("threads2.scad")
@@ -76,6 +76,24 @@ module CrystalScad
76
76
  def scad_output()
77
77
  return self.output.scad_output
78
78
  end
79
+
80
+ def threads
81
+ a = []
82
+ [:threads_top,:threads_bottom,:threads_left,:threads_right,:threads_front,:threads_back].each do |m|
83
+ if self.respond_to? m
84
+ ret = self.send m
85
+ unless ret == nil
86
+ if ret.kind_of? Array
87
+ a+= ret
88
+ else
89
+ a << ret
90
+ end
91
+ end
92
+ end
93
+ end
94
+
95
+ return a
96
+ end
79
97
 
80
98
  end
81
99
 
@@ -75,6 +75,11 @@ module CrystalScad
75
75
  self
76
76
  end
77
77
 
78
+ def rotate_around(point,args)
79
+ x,y,z= point.x, point.y, point.z
80
+ self.translate(x:-x,y:-y,z:-z).rotate(args).translate(x:x,y:y,z:z)
81
+ end
82
+
78
83
  def translate(args)
79
84
  @transformations << Translate.new(args)
80
85
  self
@@ -97,13 +102,13 @@ module CrystalScad
97
102
 
98
103
  class Rotate < Transformation
99
104
  def to_rubyscad
100
- return RubyScadBridge.new.rotate(@args)
105
+ return RubyScadBridge.new.rotate(@args).gsub('"','')
101
106
  end
102
107
  end
103
108
 
104
109
  class Translate < Transformation
105
110
  def to_rubyscad
106
- return RubyScadBridge.new.translate(@args)
111
+ return RubyScadBridge.new.translate(@args).gsub('"','')
107
112
  end
108
113
  end
109
114
 
@@ -152,6 +157,10 @@ module CrystalScad
152
157
  self
153
158
  end
154
159
 
160
+ def center
161
+ @transformations << Translate.new({x:-@x/2,y:-@y/2,z:-@z/2})
162
+ self
163
+ end
155
164
 
156
165
  def to_rubyscad
157
166
  return RubyScadBridge.new.cube(@args)
@@ -169,6 +178,17 @@ module CrystalScad
169
178
  end
170
179
  Cube.new(args)
171
180
  end
181
+
182
+ class Sphere < Primitive
183
+ def to_rubyscad
184
+ return RubyScadBridge.new.sphere(@args)
185
+ end
186
+ end
187
+
188
+ def sphere(args)
189
+ Sphere.new(args)
190
+ end
191
+
172
192
 
173
193
  # 2d primitives
174
194
  class Square < Primitive
@@ -297,7 +317,7 @@ module CrystalScad
297
317
  args.each do |a|
298
318
  if a.respond_to? :output
299
319
  r = Difference.new(r,a.output)
300
- else
320
+ else
301
321
  r = Difference.new(r,a)
302
322
  end
303
323
  end
@@ -18,7 +18,6 @@ module CrystalScad::Gears
18
18
 
19
19
  class Gear < CrystalScad::Assembly
20
20
  # this library is to be used to easily work with gears and their distances to each other
21
- # TODO: maybe at some point port the publicDomainGear.scad into it?
22
21
 
23
22
  attr_reader :module, :teeth, :height, :hub_dia, :hub_height
24
23
 
@@ -60,10 +59,87 @@ module CrystalScad::Gears
60
59
  raise "You cannot use two gears with different gear modules."
61
60
  return
62
61
  end
63
- return (@module * (@teeth + other_gear.teeth))/2.0
62
+ return (@module.to_f * (@teeth.to_f + other_gear.teeth.to_f))/2.0
63
+ end
64
+
65
+ def ratio(other_gear)
66
+ @teeth.to_f / other_gear.teeth.to_f
64
67
  end
65
68
 
66
69
  end
70
+
71
+ # Acts the same as Gear, but does produce printable output
72
+ class PrintedGear < Gear
73
+
74
+ def initialize(args={})
75
+ super
76
+ @pressure_angle = args[:pressure_angle] || 20
77
+ @clearance = args[:clearance] || 0.0
78
+ @backlash = args[:backlash] || 0.0
79
+ @twist = args[:twist] || 0.0
80
+ @teeth_to_hide = args[:teeth_to_hide] || 0.0
81
+
82
+ @rotation = args[:rotation] || 0.0 # rotation in teeth
83
+ end
84
+
85
+ def show
86
+ output
87
+ end
88
+
89
+ # ported from publicDomainGearV1.1.scad
90
+ def output
91
+ p = @module * @teeth / 2.0
92
+ c = p + @module - @clearance # radius of pitch circle
93
+ b = p*Math::cos(radians(@pressure_angle)) # radius of base circle
94
+ r = p-(c-p)-@clearance # radius of root circle
95
+ t = (@module*Math::PI)/2.0-@backlash/2.0 # tooth thickness at pitch circle
96
+ k = -iang(b, p) - t/2.0/p/Math::PI*180 # angle to where involute meets base circle on each side of tooth
97
+
98
+ points=[
99
+ [0, -@hub_dia/10.0],
100
+ polar(r, -181/@teeth.to_f),
101
+ polar(r, r<b ? k : -180/@teeth.to_f),
102
+ q7(0/5,r,b,c,k, 1),q7(1/5,r,b,c,k, 1),q7(2/5,r,b,c,k, 1),q7(3/5,r,b,c,k, 1),q7(4/5,r,b,c,k, 1),q7(5/5,r,b,c,k, 1),
103
+ q7(5/5,r,b,c,k,-1),q7(4/5,r,b,c,k,-1),q7(3/5,r,b,c,k,-1),q7(2/5,r,b,c,k,-1),q7(1/5,r,b,c,k,-1),q7(0/5,r,b,c,k,-1),
104
+ polar(r, r<b ? -k : 180/@teeth.to_f),
105
+ polar(r, 181/@teeth.to_f)
106
+ ]
107
+ paths=[(0..16).to_a]
108
+
109
+ res = CrystalScadObject.new
110
+ (0..@teeth-@teeth_to_hide-1).each do |i|
111
+ res+= polygon(points:points,paths:paths).linear_extrude(h:@height,convexity:10,center:false,twist:@twist).rotate(z:i*360/@teeth.to_f)
112
+ end
113
+
114
+ res-= cylinder(h:@height+0.2,d:@bore).translate(z:-0.1)
115
+ res.rotate(z:@rotation*360.0/@teeth)
116
+ end
117
+
118
+ def radians(a)
119
+ a/180.0 * Math::PI
120
+ end
121
+
122
+ def degrees(a)
123
+ a*180 / Math::PI
124
+ end
125
+
126
+ def polar(r,theta)
127
+ [r*Math::sin(radians(theta)), r*Math::cos(radians(theta))] #convert polar to cartesian coordinates
128
+ end
129
+
130
+ def iang(r1,r2)
131
+ Math::sqrt((r2/r1)*(r2/r1) - 1)/Math::PI*180 - degrees(Math::acos(r1/r2)) #//unwind a string this many degrees to go from radius r1 to radius r2
132
+ end
133
+
134
+ def q7(f,r,b,r2,t,s)
135
+ q6(b,s,t,(1-f)*[b,r].max+f*r2) #radius a fraction f up the curved side of the tooth
136
+ end
137
+
138
+ def q6(b,s,t,d)
139
+ polar(d,s*(iang(b,d)+t)) # point at radius d on the involute curve
140
+ end
141
+
142
+ end
67
143
 
68
144
  end
69
145
 
@@ -17,7 +17,7 @@ module CrystalScad::ScrewThreads
17
17
  class ScrewThread
18
18
  # I would name this Thread but that's already taken by something else
19
19
 
20
- attr_accessor :x,:y,:z,:size, :depth
20
+ attr_accessor :x,:y,:z,:size, :depth, :face
21
21
 
22
22
  def initialize(args={})
23
23
  @x = args[:x] || 0
@@ -25,6 +25,52 @@ module CrystalScad::ScrewThreads
25
25
  @z = args[:z] || 0
26
26
  @depth = args[:depth]
27
27
  @size = args[:size]
28
+ @face = args[:face] || :top
29
+ end
30
+
31
+ def rotation
32
+ case @face.to_s
33
+ when "top"
34
+ return {}
35
+ when "bottom"
36
+ return {y:180}
37
+ when "left"
38
+ return {y:-90}
39
+ when "right"
40
+ return {y:90}
41
+ when "front" # checkme
42
+ return {x:90}
43
+ when "back"
44
+ return {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 orientation_swap_to(coords,rotation)
53
+ if rotation[:x].to_i == -90
54
+ return [coords[0],coords[2],-coords[1]]
55
+ end
56
+ if rotation[:x].to_i == 90
57
+ return [coords[0],-coords[2],coords[1]]
58
+ end
59
+ if rotation[:y].to_i == -90
60
+ return [coords[2],coords[1],coords[0]]
61
+ end
62
+ if rotation[:y].to_i == 90
63
+ return [-coords[2],coords[1],-coords[0]]
64
+ end
65
+
66
+ return coords
67
+ end
68
+
69
+ def position_on(other_thread,rotation={})
70
+ oc = other_thread.x, other_thread.y, other_thread.z
71
+ oc = orientation_swap_to(oc,rotation)
72
+
73
+ return {x:@x-oc[0],y:@y-oc[1],z:@z-oc[2]}
28
74
  end
29
75
 
30
76
  end
@@ -39,7 +85,7 @@ module CrystalScad::ScrewThreads
39
85
 
40
86
  # we need to know obj1 height (if not supplied by user)
41
87
  height ||= args[:height]
42
- case face
88
+ case face.to_s
43
89
  when "top"
44
90
  height ||= obj1.z rescue nil
45
91
  when "bottom"
@@ -92,7 +138,6 @@ module CrystalScad::ScrewThreads
92
138
  ret = []
93
139
  holes.each_with_index do |hole,i|
94
140
  bolt = Bolt.new(hole.size,bolt_heights[i])
95
- puts bolt_heights[i]
96
141
  case face
97
142
  when "top"
98
143
  bolt.transformations << Rotate.new(x:180)
@@ -117,6 +162,6 @@ module CrystalScad::ScrewThreads
117
162
  end
118
163
 
119
164
  ret
120
- end
165
+ end
121
166
 
122
167
  end
@@ -1,4 +1,4 @@
1
1
  module CrystalScad
2
- VERSION = "0.3.7"
2
+ VERSION = "0.3.8"
3
3
  end
4
4
 
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: crystalscad
3
3
  version: !ruby/object:Gem::Version
4
- hash: 29
4
+ hash: 3
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 3
9
- - 7
10
- version: 0.3.7
9
+ - 8
10
+ version: 0.3.8
11
11
  platform: ruby
12
12
  authors:
13
13
  - Joachim Glauche
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2013-12-29 00:00:00 Z
18
+ date: 2014-01-05 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: rubyscad
@@ -63,8 +63,15 @@ files:
63
63
  - Rakefile
64
64
  - crystalscad.gemspec
65
65
  - examples/gear.rb
66
+ - examples/openscad_examples/example001.rb
67
+ - examples/openscad_examples/example002.rb
68
+ - examples/openscad_examples/example003.rb
69
+ - examples/openscad_examples/example004.rb
70
+ - examples/openscad_examples/example005.rb
71
+ - examples/printed_gear.rb
66
72
  - examples/stack.rb
67
73
  - examples/threads.rb
74
+ - examples/threads2.rb
68
75
  - lib/crystalscad.rb
69
76
  - lib/crystalscad/Assembly.rb
70
77
  - lib/crystalscad/BillOfMaterial.rb