crystalscad 0.3.7 → 0.3.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,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