engineering 0.2 → 0.3
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 +4 -4
- data/.travis.yml +11 -0
- data/Gemfile +6 -2
- data/Rakefile +2 -0
- data/engineering.gemspec +8 -6
- data/lib/builder/extrusion.rb +189 -0
- data/lib/builder/model.rb +120 -0
- data/lib/builder/sketch.rb +119 -0
- data/lib/engineering.rb +28 -54
- data/lib/model/dsl.rb +26 -0
- data/lib/sketchup.rb +25 -5
- data/test/builder/extrusion.rb +143 -0
- data/test/builder/model.rb +191 -0
- data/test/builder/sketch.rb +161 -0
- data/test/engineering.rb +95 -30
- data/test/fixtures/sketchup/sketch_group_group.su +4 -0
- data/test/fixtures/sketchup/sketch_group_group_group.su +4 -0
- data/test/sketchup/builder.rb +43 -9
- metadata +42 -27
@@ -0,0 +1,161 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require 'builder/sketch'
|
3
|
+
|
4
|
+
describe Engineering::Builder::Sketch do
|
5
|
+
subject { Engineering::Builder::Sketch }
|
6
|
+
|
7
|
+
it 'must build a subclass' do
|
8
|
+
subject.build.ancestors.must_include(Sketch)
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'must build a subclass with an empty block' do
|
12
|
+
klass = subject.build {}
|
13
|
+
klass.ancestors.must_include(Sketch)
|
14
|
+
klass.elements.must_be_empty
|
15
|
+
Class.wont_be :respond_to?, :elements
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'must build a subclass that contains a single element' do
|
19
|
+
klass = subject.build do
|
20
|
+
rectangle from:[0,0], to:[1,1]
|
21
|
+
end
|
22
|
+
klass.elements.count.must_equal 1
|
23
|
+
klass.elements.first.must_be_instance_of Geometry::Rectangle
|
24
|
+
end
|
25
|
+
|
26
|
+
describe 'when creating a subclass with attributes' do
|
27
|
+
let :klass do
|
28
|
+
subject.build do
|
29
|
+
attribute :attribute0
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'must define the attributes for instances' do
|
34
|
+
klass.new.must_be :respond_to?, :attribute0
|
35
|
+
klass.new.must_be :respond_to?, :attribute0=
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'must have working instance accessors' do
|
39
|
+
test_model = klass.new
|
40
|
+
test_model.attribute0 = 42
|
41
|
+
test_model.attribute0.must_equal 42
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'must be able to initialize the attribute during construction' do
|
45
|
+
klass.new(attribute0: 37).attribute0.must_equal 37
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe 'when creating a subclass with attributes that have default values' do
|
50
|
+
let :klass do
|
51
|
+
subject.build do
|
52
|
+
attribute :attribute0, 42
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'must have the default value' do
|
57
|
+
klass.new.attribute0.must_equal 42
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'must allow the default value to be overriden' do
|
61
|
+
klass.new(attribute0: 24).attribute0.must_equal 24
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'must have class attributes' do
|
65
|
+
klass.attribute0.must_equal 42
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'must not pollute Class' do
|
69
|
+
Class.wont_be :respond_to?, :attribute0
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'must not have a class setter' do
|
73
|
+
-> { klass.attribute0 = 5 }.must_raise NoMethodError
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
describe 'when creating a subclass with read-only attributes that have default values' do
|
78
|
+
let :klass do
|
79
|
+
subject.build do
|
80
|
+
attr_reader :attributeO, 42
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'must have the default value' do
|
85
|
+
klass.new.attributeO.must_equal 42
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'must not allow the default value to be overriden' do
|
89
|
+
-> { klass.new(attributeO: 24) }.must_raise NoMethodError
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'must not pollute Class' do
|
93
|
+
Class.wont_be :respond_to?, :attribute0
|
94
|
+
end
|
95
|
+
|
96
|
+
it 'must have class attributes' do
|
97
|
+
klass.attributeO.must_equal 42
|
98
|
+
end
|
99
|
+
|
100
|
+
it 'must not have a class setter' do
|
101
|
+
-> { klass.attributeO = 5 }.must_raise NoMethodError
|
102
|
+
end
|
103
|
+
|
104
|
+
it 'must not have an instance setter' do
|
105
|
+
-> { klass.new.attributeO = 6 }.must_raise NoMethodError
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
describe 'when creating a subclass with a group' do
|
110
|
+
let :klass do
|
111
|
+
subject.build do
|
112
|
+
group origin:[1,2] do
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
it 'must create a Group subclass' do
|
118
|
+
klass.elements.count.must_equal 1
|
119
|
+
klass.elements.first.first.ancestors.must_include Sketch::Group
|
120
|
+
klass.elements.first.last.must_equal [origin:[1,2]]
|
121
|
+
end
|
122
|
+
|
123
|
+
it 'must pass the initializer arguments when instantiating the subclass' do
|
124
|
+
klass.new.first.must_be_kind_of Sketch::Group
|
125
|
+
klass.new.first.transformation.translation.must_equal Geometry::Point[1,2]
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
describe 'when creating a subclass that contains another Sketch subclass' do
|
130
|
+
let :klass do
|
131
|
+
subject.build do
|
132
|
+
push Sketch
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
it 'must add the subclass' do
|
137
|
+
klass.elements.length.must_equal 1
|
138
|
+
klass.elements.first.first.ancestors.must_include Sketch
|
139
|
+
klass.elements.first.last.must_equal []
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
describe 'when creating a subclass that contains another Sketch subclass that has argument' do
|
144
|
+
let :klass do
|
145
|
+
subject.build do
|
146
|
+
push Sketch, origin:[1,2]
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
it 'must add the subclass' do
|
151
|
+
klass.elements.length.must_equal 1
|
152
|
+
klass.elements.first.first.ancestors.must_include Sketch
|
153
|
+
klass.elements.first.last.must_equal [origin:[1,2]]
|
154
|
+
end
|
155
|
+
|
156
|
+
it 'must pass the initializer arguments when instantiating the subclass' do
|
157
|
+
klass.new.first.must_be_kind_of Sketch
|
158
|
+
klass.new.first.transformation.translation.must_equal Geometry::Point[1,2]
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
data/test/engineering.rb
CHANGED
@@ -24,7 +24,6 @@ describe Engineering do
|
|
24
24
|
end
|
25
25
|
end
|
26
26
|
end
|
27
|
-
let(:testModel) { TestModel.new }
|
28
27
|
|
29
28
|
it "must create a global constant" do
|
30
29
|
Object.constants.include?(:TestModel).must_equal true
|
@@ -37,7 +36,7 @@ describe Engineering do
|
|
37
36
|
|
38
37
|
it "must call the initializer block when constructed" do
|
39
38
|
TestModel.new.elements.count.must_equal 1
|
40
|
-
TestModel.new.elements.first.
|
39
|
+
TestModel.new.elements.first.must_be_kind_of Model::Extrusion
|
41
40
|
TestModel.new.elements.first.length.must_equal 10
|
42
41
|
end
|
43
42
|
|
@@ -49,18 +48,18 @@ describe Engineering do
|
|
49
48
|
end
|
50
49
|
end
|
51
50
|
end
|
52
|
-
|
51
|
+
subject { TestModel2.new }
|
53
52
|
|
54
53
|
it "must be able to make new instances" do
|
55
|
-
|
56
|
-
|
57
|
-
|
54
|
+
subject.must_be_kind_of Model
|
55
|
+
subject.must_be_instance_of TestModel2
|
56
|
+
subject.wont_be_instance_of TestModel
|
58
57
|
end
|
59
58
|
|
60
59
|
it "must call the correct initializer block when constructed" do
|
61
|
-
|
62
|
-
|
63
|
-
|
60
|
+
subject.elements.count.must_equal 1
|
61
|
+
subject.elements.first.must_be_kind_of Model::Extrusion
|
62
|
+
subject.elements.first.length.must_equal 5
|
64
63
|
end
|
65
64
|
|
66
65
|
describe "when the original Model class is used again" do
|
@@ -68,13 +67,22 @@ describe Engineering do
|
|
68
67
|
|
69
68
|
it "must call the correct initializer block when constructed" do
|
70
69
|
anotherTestModel.elements.count.must_equal 1
|
71
|
-
anotherTestModel.elements.first.
|
70
|
+
anotherTestModel.elements.first.must_be_kind_of Model::Extrusion
|
72
71
|
anotherTestModel.elements.first.length.must_equal 10
|
73
72
|
end
|
74
73
|
end
|
75
74
|
end
|
76
75
|
end
|
77
76
|
|
77
|
+
it 'must create a Model subclass inside of a Module' do
|
78
|
+
module TestModule
|
79
|
+
model :TestModel5 do
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
TestModule.constants.include?(:TestModel5).must_equal true
|
84
|
+
end
|
85
|
+
|
78
86
|
describe 'when creating a Model subclass with attributes' do
|
79
87
|
before do
|
80
88
|
model :TestModel4 do
|
@@ -100,7 +108,7 @@ describe Engineering do
|
|
100
108
|
|
101
109
|
describe 'when creating a Model subclass with attributes that have default values' do
|
102
110
|
subject do
|
103
|
-
model
|
111
|
+
model do
|
104
112
|
attribute :attribute0, 42
|
105
113
|
end
|
106
114
|
end
|
@@ -112,6 +120,42 @@ describe Engineering do
|
|
112
120
|
it 'must allow the default value to be overriden' do
|
113
121
|
subject.new(attribute0: 24).attribute0.must_equal 24
|
114
122
|
end
|
123
|
+
|
124
|
+
it 'must have class attributes' do
|
125
|
+
subject.attribute0.must_equal 42
|
126
|
+
end
|
127
|
+
|
128
|
+
it 'must not have a class setter' do
|
129
|
+
-> { subject.attribute0 = 5 }.must_raise NoMethodError
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
describe 'when creating a Model subclass with read-only attributes that have default values' do
|
134
|
+
subject do
|
135
|
+
model do
|
136
|
+
attr_reader :attributeRO, 42
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
it 'must have the default value' do
|
141
|
+
subject.new.attributeRO.must_equal 42
|
142
|
+
end
|
143
|
+
|
144
|
+
it 'must not allow the default value to be overriden' do
|
145
|
+
-> { subject.new(attributeRO: 24) }.must_raise NoMethodError
|
146
|
+
end
|
147
|
+
|
148
|
+
it 'must have class attributes' do
|
149
|
+
subject.attributeRO.must_equal 42
|
150
|
+
end
|
151
|
+
|
152
|
+
it 'must not have a class setter' do
|
153
|
+
-> { subject.attributeRO = 5 }.must_raise NoMethodError
|
154
|
+
end
|
155
|
+
|
156
|
+
it 'must not have an instance setter' do
|
157
|
+
-> { subject.new.attributeRO = 6 }.must_raise NoMethodError
|
158
|
+
end
|
115
159
|
end
|
116
160
|
|
117
161
|
describe "when creating an Extrusion subclass" do
|
@@ -134,7 +178,7 @@ describe Engineering do
|
|
134
178
|
end
|
135
179
|
|
136
180
|
it 'must have a class attribute for the Sketch' do
|
137
|
-
TestExtrusion.sketch.
|
181
|
+
TestExtrusion.sketch.ancestors.must_include Sketch
|
138
182
|
end
|
139
183
|
|
140
184
|
describe "when initializing a new instance" do
|
@@ -151,28 +195,49 @@ describe Engineering do
|
|
151
195
|
end
|
152
196
|
|
153
197
|
describe 'when creating an Extrusion subclass with a length' do
|
154
|
-
|
155
|
-
|
156
|
-
before do
|
157
|
-
extrusion :TestExtrusion do
|
198
|
+
subject do
|
199
|
+
extrusion do
|
158
200
|
length 10
|
159
201
|
square 5
|
160
202
|
end
|
161
203
|
end
|
162
204
|
|
163
205
|
it 'must have a class attribute for the length' do
|
164
|
-
|
206
|
+
subject.length.must_equal 10
|
165
207
|
end
|
166
208
|
|
167
209
|
describe 'when initializing a new instance' do
|
168
210
|
it 'must reject a length argument' do
|
169
|
-
-> {
|
211
|
+
-> { subject.new(length:5) }.must_raise ArgumentError
|
170
212
|
end
|
171
213
|
|
172
214
|
it 'must have the proper length' do
|
173
|
-
|
215
|
+
subject.new.length.must_equal 10
|
216
|
+
end
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
describe 'when creating an Extrusion subclass with attributes' do
|
221
|
+
subject do
|
222
|
+
extrusion do
|
223
|
+
attribute :attribute0
|
174
224
|
end
|
175
225
|
end
|
226
|
+
|
227
|
+
it 'must define the attributes' do
|
228
|
+
subject.new.must_be :respond_to?, :attribute0
|
229
|
+
subject.new.must_be :respond_to?, :attribute0=
|
230
|
+
end
|
231
|
+
|
232
|
+
it 'must have working accessors' do
|
233
|
+
test_model = subject.new
|
234
|
+
test_model.attribute0 = 42
|
235
|
+
test_model.attribute0.must_equal 42
|
236
|
+
end
|
237
|
+
|
238
|
+
it 'must be able to initialize the attribute during construction' do
|
239
|
+
subject.new(attribute0: 37).attribute0.must_equal 37
|
240
|
+
end
|
176
241
|
end
|
177
242
|
|
178
243
|
describe "when creating a Model that uses global constants" do
|
@@ -197,20 +262,20 @@ describe Engineering do
|
|
197
262
|
square 5
|
198
263
|
end
|
199
264
|
end
|
200
|
-
|
265
|
+
subject { TestSketch.new }
|
201
266
|
|
202
267
|
it "must create a global constant" do
|
203
268
|
Object.constants.include?(:TestSketch).must_equal true
|
204
269
|
end
|
205
270
|
|
206
271
|
it "must support creating instances of the subclass" do
|
207
|
-
|
208
|
-
|
272
|
+
subject.must_be_kind_of Sketch
|
273
|
+
subject.must_be_kind_of TestSketch
|
209
274
|
end
|
210
275
|
|
211
276
|
it "must call the initializer block when constructed" do
|
212
|
-
|
213
|
-
|
277
|
+
subject.elements.count.must_equal 1
|
278
|
+
subject.elements.first.must_be_kind_of Geometry::Square
|
214
279
|
end
|
215
280
|
|
216
281
|
describe "when another sketch class is created with a new name" do
|
@@ -219,17 +284,17 @@ describe Engineering do
|
|
219
284
|
square 10
|
220
285
|
end
|
221
286
|
end
|
222
|
-
|
287
|
+
subject { TestSketch2.new }
|
223
288
|
|
224
289
|
it "must be able to make new instances" do
|
225
|
-
|
226
|
-
|
227
|
-
|
290
|
+
subject.must_be_kind_of Sketch
|
291
|
+
subject.must_be_kind_of TestSketch2
|
292
|
+
subject.wont_be_kind_of TestSketch
|
228
293
|
end
|
229
294
|
|
230
295
|
it "must call the correct initializer block when constructed" do
|
231
|
-
|
232
|
-
|
296
|
+
subject.elements.count.must_equal 1
|
297
|
+
subject.elements.first.must_be_kind_of Geometry::Square
|
233
298
|
end
|
234
299
|
|
235
300
|
describe "when the original Sketch class is used again" do
|
@@ -0,0 +1,4 @@
|
|
1
|
+
model = Sketchup.active_model
|
2
|
+
model.entities.clear!
|
3
|
+
model.definitions.purge_unused
|
4
|
+
lambda{ points = model.entities.add_circle(Geom::Point3d.new(0, 0).transform!(Geom::Transformation.new([4, 6],[1,0,0],[0,1,0])), [0,0,1], 0.5); points[0].find_faces; points[0].faces[0]}.call
|
@@ -0,0 +1,4 @@
|
|
1
|
+
model = Sketchup.active_model
|
2
|
+
model.entities.clear!
|
3
|
+
model.definitions.purge_unused
|
4
|
+
lambda{ points = model.entities.add_circle(Geom::Point3d.new(0, 0).transform!(Geom::Transformation.new([9, 12],[1,0,0],[0,1,0])), [0,0,1], 0.5); points[0].find_faces; points[0].faces[0]}.call
|
data/test/sketchup/builder.rb
CHANGED
@@ -40,7 +40,7 @@ describe SketchUp::Builder do
|
|
40
40
|
|
41
41
|
describe "when given a Model of a translated Extrusion" do
|
42
42
|
sketch = Sketch.new
|
43
|
-
sketch.
|
43
|
+
sketch.push Geometry::Rectangle.new size:[10, 20]
|
44
44
|
before do
|
45
45
|
subject.container = Model.new do
|
46
46
|
push Model::Extrusion.new(length:5, sketch:sketch, transformation:Geometry::Transformation.new(origin:[1,2,3]))
|
@@ -54,7 +54,7 @@ describe SketchUp::Builder do
|
|
54
54
|
|
55
55
|
it "should generate the correct text from a Model of a simple extrusion" do
|
56
56
|
sketch = Sketch.new
|
57
|
-
sketch.
|
57
|
+
sketch.push Geometry::Rectangle.new size:[10, 20]
|
58
58
|
model = Model.new do
|
59
59
|
push Model::Extrusion.new(length:5, sketch:sketch)
|
60
60
|
end
|
@@ -64,7 +64,7 @@ describe SketchUp::Builder do
|
|
64
64
|
|
65
65
|
it "should generate the correct text from a Model of a simple extrusion with units" do
|
66
66
|
sketch = Sketch.new
|
67
|
-
sketch.
|
67
|
+
sketch.push Geometry::Rectangle.new size:[1.meter, 10]
|
68
68
|
model = Model.new
|
69
69
|
model.push Model::Extrusion.new(length:5.meters, sketch:sketch)
|
70
70
|
@builder.container = model
|
@@ -78,7 +78,7 @@ describe SketchUp::Builder do
|
|
78
78
|
|
79
79
|
it "should generate correct text from a simple Sketch object" do
|
80
80
|
sketch = Sketch.new
|
81
|
-
sketch.
|
81
|
+
sketch.push Geometry::Line[[0,0], [1,0]]
|
82
82
|
@builder.container = sketch
|
83
83
|
@builder.to_s.must_equal File.read('test/fixtures/sketchup/line_sketch.su')
|
84
84
|
end
|
@@ -86,20 +86,21 @@ describe SketchUp::Builder do
|
|
86
86
|
describe "when given a Sketch" do
|
87
87
|
it "must RegularPolygon" do
|
88
88
|
subject.container = Sketch.new.tap {|s| s.push RegularPolygon.new(sides:6, center:[0,0], radius:5) }
|
89
|
-
|
89
|
+
expected = %r{model = Sketchup.active_model\nmodel.entities.clear!\nmodel.definitions.purge_unused\nmodel.entities.add_face\(\[5.0, 0.0\], \[2.5000000000000\d+, 4.330127018922\d+\], \[-2.49999999999\d+, 4.3301270189221\d+\], \[-5.0, 6.123233995736766e-16\], \[-2.5000000000\d+, -4.330127018922\d+\], \[2.4999999999999\d+, -4.330127018922\d+\]\)}
|
90
|
+
subject.to_s.must_match expected
|
90
91
|
end
|
91
92
|
end
|
92
93
|
|
93
94
|
it "should generate correct text from a Sketch object with a single Rectangle" do
|
94
95
|
sketch = Sketch.new
|
95
|
-
sketch.
|
96
|
+
sketch.push Geometry::Rectangle.new origin:[0,0], size:[1,1]
|
96
97
|
@builder.container = sketch
|
97
98
|
@builder.to_s.must_equal rectangle_sketch_fixture
|
98
99
|
end
|
99
100
|
|
100
101
|
it "should generate correct text from a Sketch object with a single Polygon" do
|
101
102
|
sketch = Sketch.new
|
102
|
-
sketch.
|
103
|
+
sketch.push Polygon.new [0,0], [0,1], [1,1], [1,0], [0,0]
|
103
104
|
@builder.container = sketch
|
104
105
|
@builder.to_s.must_equal rectangle_sketch_fixture
|
105
106
|
end
|
@@ -113,7 +114,6 @@ describe SketchUp::Builder do
|
|
113
114
|
|
114
115
|
it "must handle a sub-model" do
|
115
116
|
builder = SketchUp::Builder.new( Model::Builder.new.evaluate { push Model.new, :origin => [3,2,1] })
|
116
|
-
builder.container.elements.count.must_equal 1
|
117
117
|
builder.container.elements.first.must_be_instance_of(Model)
|
118
118
|
builder.to_s.must_match %r{model = Sketchup.active_model\nmodel.entities.clear!\nmodel.definitions.purge_unused\nlambda {|m|\n\t\n}.call(model.definitions.add('Model(\d+)'))\nmodel.entities.add_instance(model.definitions\['Model(\d+)'\], Geom::Transformation.new(\[3, 2, 1\],\[1,0,0\],\[0,1,0\]))}
|
119
119
|
end
|
@@ -129,12 +129,46 @@ describe SketchUp::Builder do
|
|
129
129
|
it "must generate the correct text" do
|
130
130
|
subject.to_s.must_equal File.read('test/fixtures/sketchup/sketch_group.su')
|
131
131
|
end
|
132
|
+
|
133
|
+
describe 'when the Group contains a Group' do
|
134
|
+
before do
|
135
|
+
subject.container = Sketch::Builder.new do
|
136
|
+
group origin:[1,2] do
|
137
|
+
group origin:[3,4] do
|
138
|
+
circle diameter:1
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end.sketch
|
142
|
+
end
|
143
|
+
|
144
|
+
it 'must generate the correct text' do
|
145
|
+
subject.to_s.must_equal File.read('test/fixtures/sketchup/sketch_group_group.su')
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
describe 'when the Group contains a Group with a Group' do
|
150
|
+
before do
|
151
|
+
subject.container = Sketch::Builder.new do
|
152
|
+
group origin:[1,2] do
|
153
|
+
group origin:[3,4] do
|
154
|
+
group origin:[5,6] do
|
155
|
+
circle diameter:1
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end.sketch
|
160
|
+
end
|
161
|
+
|
162
|
+
it 'must generate the correct text' do
|
163
|
+
subject.to_s.must_equal File.read('test/fixtures/sketchup/sketch_group_group_group.su')
|
164
|
+
end
|
165
|
+
end
|
132
166
|
end
|
133
167
|
end
|
134
168
|
|
135
169
|
it "Path" do
|
136
170
|
sketch = Sketch.new
|
137
|
-
sketch.
|
171
|
+
sketch.push Path.new [0,0], Geometry::Arc.new(center:[0,0], radius:5, start:0, end:90*Math::PI/180), [0,0]
|
138
172
|
builder = SketchUp::Builder.new( Model::Builder.new.evaluate { extrude length:5, sketch:sketch })
|
139
173
|
end
|
140
174
|
end
|