radmesh 0.98.1

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.
data/radmesh.gemspec ADDED
@@ -0,0 +1,21 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'radmesh'
3
+ s.version = '0.98.1'
4
+ s.date = Time.now.strftime('%Y-%m-%d')
5
+ s.summary = 'Ruby wrapper around ADMesh'
6
+ s.description = <<-eof
7
+ ADMesh is a library for processing triangulated solid meshes.
8
+ Currently, ADMesh only reads the STL file format that is used
9
+ for rapid prototyping applications, although it can write STL,
10
+ VRML, OFF, and DXF files. Those are bindings for Ruby.
11
+ You'll need the ADMesh C library in version 0.98.x.
12
+ eof
13
+ s.authors = ['Miro Hrončok']
14
+ s.email = 'miro@hroncok.cz'
15
+ s.files = Dir.glob('{doc,lib,spec}/**/*') +
16
+ ['README.md', 'LICENSE', 'Rakefile', 'Gemfile', 'block.stl', __FILE__]
17
+ s.homepage =
18
+ 'https://github.com/admesh/rubygem-admesh'
19
+ s.platform = Gem::Platform::RUBY
20
+ s.license = 'GPL-2.0+'
21
+ end
@@ -0,0 +1,269 @@
1
+ gem 'minitest'
2
+ require 'minitest/autorun'
3
+ require 'radmesh'
4
+
5
+ describe RADMesh::STL do
6
+ before do
7
+ @stl = RADMesh::STL.new 'block.stl'
8
+ @axes = [:x, :y, :z]
9
+ end
10
+
11
+ describe 'block.stl' do
12
+ it 'must have 12 facets' do
13
+ @stl.stats[:number_of_facets].must_equal 12
14
+ end
15
+ it 'must have "solid admesh" header' do
16
+ @stl.stats[:header].must_equal 'solid admesh'
17
+ end
18
+ it 'must calculate volume to 1' do
19
+ @stl.calculate_volume!.stats[:volume].must_equal 1
20
+ end
21
+ it 'must have size 1 for each axis' do
22
+ @axes.each do |axis|
23
+ @stl.stats[:size][axis].must_equal 1
24
+ end
25
+ end
26
+ it 'must have max 1 for each axis' do
27
+ @axes.each do |axis|
28
+ @stl.stats[:max][axis].must_equal 1
29
+ end
30
+ end
31
+ it 'must have min 0 for each axis' do
32
+ @axes.each do |axis|
33
+ @stl.stats[:min][axis].must_equal 0
34
+ end
35
+ end
36
+ it 'must be recognized as ASCII' do
37
+ @stl.stats[:type].must_equal :ascii
38
+ end
39
+ it 'must be able to write as ASCII STL' do
40
+ @stl.write_ascii '.block_ascii.stl'
41
+ stl_ascii = RADMesh::STL.new '.block_ascii.stl'
42
+ stl_ascii.stats[:type].must_equal :ascii
43
+ end
44
+ it 'must be able to write as binary STL' do
45
+ @stl.write_binary '.block_binary.stl'
46
+ stl_binary = RADMesh::STL.new '.block_binary.stl'
47
+ stl_binary.stats[:type].must_equal :binary
48
+ end
49
+ it 'must be able to write as OBJ' do
50
+ @stl.write_obj '.block.obj'
51
+ end
52
+ it 'must be able to write as OFF' do
53
+ @stl.write_off '.block.off'
54
+ end
55
+ it 'must be able to write as DXF' do
56
+ @stl.write_dxf '.block.dxf'
57
+ end
58
+ it 'must be able to write as VRML' do
59
+ @stl.write_vrml '.block.vrml'
60
+ end
61
+ it 'must check nerby facets without blow up' do
62
+ @stl.check_facets_nearby! 0.001
63
+ end
64
+ it 'must remove unconnected facets without blow up' do
65
+ @stl.remove_unconnected_facets!
66
+ end
67
+ it 'must verify neighbors without blow up' do
68
+ skip 'this is very verbose'
69
+ @stl.verify_neighbors!
70
+ end
71
+ it 'must fill holes without blow up' do
72
+ @stl.fill_holes!
73
+ end
74
+ it 'must fix normal directions without blow up' do
75
+ @stl.fix_normal_directions!
76
+ end
77
+ it 'must fix normal values without blow up' do
78
+ @stl.fix_normal_values!
79
+ end
80
+ it 'must reverse all facets correctly' do
81
+ @stl.reverse_all_facets!
82
+ @stl.calculate_volume!.stats[:volume].must_equal(-1)
83
+ @stl.reverse_all_facets!
84
+ @stl.calculate_volume!.stats[:volume].must_equal 1
85
+ end
86
+ it 'must translate to absolute coordinates' do
87
+ @stl.translate! 10, 20, 30
88
+ @stl.stats[:min][:x].must_equal 10
89
+ @stl.stats[:min][:y].must_equal 20
90
+ @stl.stats[:min][:z].must_equal 30
91
+ end
92
+ it 'must translate to absolute coordinates array' do
93
+ @stl.translate! [0, 20, 30]
94
+ @stl.stats[:min][:x].must_equal 0
95
+ @stl.stats[:min][:y].must_equal 20
96
+ @stl.stats[:min][:z].must_equal 30
97
+ end
98
+ it 'must translate to absolute coordinates hash' do
99
+ @stl.translate! y: 20, z: 30
100
+ @stl.stats[:min][:x].must_equal 0
101
+ @stl.stats[:min][:y].must_equal 20
102
+ @stl.stats[:min][:z].must_equal 30
103
+ end
104
+ it 'must translate by relative coordinates' do
105
+ @stl.translate_relative! 0, 10, 15
106
+ @stl.translate_relative! 0, 10, 15
107
+ @stl.stats[:min][:x].must_equal 0
108
+ @stl.stats[:min][:y].must_equal 20
109
+ @stl.stats[:min][:z].must_equal 30
110
+ end
111
+ it 'must translate by relative coordinates array' do
112
+ @stl.translate_relative! [0, 10, 15]
113
+ @stl.translate_relative! [0, 10, 15]
114
+ @stl.stats[:min][:x].must_equal 0
115
+ @stl.stats[:min][:y].must_equal 20
116
+ @stl.stats[:min][:z].must_equal 30
117
+ end
118
+ it 'must translate by relative coordinates hash' do
119
+ @stl.translate_relative! y: 10, z: 15
120
+ @stl.translate_relative! y: 10, z: 15
121
+ @stl.stats[:min][:x].must_equal 0
122
+ @stl.stats[:min][:y].must_equal 20
123
+ @stl.stats[:min][:z].must_equal 30
124
+ end
125
+ it 'must scale by factor' do
126
+ @stl.scale! 50
127
+ @axes.each do |axis|
128
+ @stl.stats[:size][axis].must_equal 50
129
+ end
130
+ @stl.scale! 10
131
+ @axes.each do |axis|
132
+ @stl.stats[:size][axis].must_equal 500
133
+ end
134
+ @stl.scale!(1.0 / 500)
135
+ @axes.each do |axis|
136
+ @stl.stats[:size][axis].must_equal 1
137
+ end
138
+ end
139
+ it 'must scale by versor' do
140
+ @stl.scale_versor! 1, 10, 100
141
+ @stl.stats[:size][:x].must_equal 1
142
+ @stl.stats[:size][:y].must_equal 10
143
+ @stl.stats[:size][:z].must_equal 100
144
+ end
145
+ it 'must scale by versor as array' do
146
+ @stl.scale_versor! [1, 10, 100]
147
+ @stl.stats[:size][:x].must_equal 1
148
+ @stl.stats[:size][:y].must_equal 10
149
+ @stl.stats[:size][:z].must_equal 100
150
+ end
151
+ it 'must scale by versor as hash' do
152
+ @stl.scale_versor! y: 10, z: 100
153
+ @stl.stats[:size][:x].must_equal 1
154
+ @stl.stats[:size][:y].must_equal 10
155
+ @stl.stats[:size][:z].must_equal 100
156
+ end
157
+ it 'must rotate by each axis' do
158
+ @axes.each_with_index do |axis, idx|
159
+ @stl.rotate!(axis, 45)
160
+ check_axis = @axes[(idx + 1) % 3]
161
+ @stl.stats[:size][axis].must_be_within_epsilon 1
162
+ @stl.stats[:size][check_axis].must_be_within_epsilon 1.414
163
+ @stl.rotate!(axis, -45)
164
+ end
165
+ end
166
+ it 'must not rotate by bad axis' do
167
+ proc { @stl.rotate! :o, 45 }.must_raise ArgumentError
168
+ end
169
+ it 'must mirror by each axis pair' do
170
+ @axes.each_with_index do |axis, idx|
171
+ a1 = @axes[(idx + 1) % 3]
172
+ a2 = @axes[(idx + 2) % 3]
173
+ @stl.mirror! a1, a2 # two arguments
174
+ @stl.stats[:min][axis].must_equal(-1)
175
+ @stl.stats[:max][axis].must_equal 0
176
+ @stl.mirror! [a1, a2] # one array argument
177
+ @stl.stats[:min][axis].must_equal 0
178
+ @stl.stats[:max][axis].must_equal 1
179
+ end
180
+ end
181
+ it 'must not mirror by too many axes' do
182
+ proc { @stl.mirror! :x, :y, :z }.must_raise ArgumentError
183
+ end
184
+ it 'must not mirror by too few axes' do
185
+ proc { @stl.mirror! :x }.must_raise ArgumentError
186
+ end
187
+ it 'must not mirror by bad axis' do
188
+ proc { @stl.mirror! :x, :o }.must_raise ArgumentError
189
+ end
190
+ it 'must open merge other STLs' do
191
+ @stl.translate! 10, 10, 10
192
+ @stl.open_merge! 'block.stl'
193
+ @stl.calculate_volume!.stats[:volume].must_equal 2
194
+ end
195
+ it 'must repair without blowing up' do
196
+ @stl.repair! verbose: false
197
+ end
198
+ it 'must repair with set tolerance' do
199
+ @stl.repair! tolerance: 0.2, verbose: false
200
+ end
201
+ it 'must have size 12' do
202
+ @stl.size.must_equal 12
203
+ end
204
+ it 'must give array of size 12' do
205
+ @stl.to_a.size.must_equal 12
206
+ end
207
+ it 'must access facets on index' do
208
+ # don't rally test extra, because it might be random rubbish
209
+ @stl[5].merge(extra: ' ').must_equal normal: { x: 0, y: -1, z: -0 },
210
+ vertex: [{ x: 1, y: 0, z: 1 },
211
+ { x: 0, y: 0, z: 0 },
212
+ { x: 1, y: 0, z: 0 }],
213
+ extra: ' '
214
+ end
215
+ it 'must blow up when accessing facets on index out of range' do
216
+ proc { @stl[13] }.must_raise IndexError
217
+ end
218
+ it 'must walk facets' do
219
+ count = 0
220
+ @stl.each_facet do |facet|
221
+ facet.must_be_kind_of Hash
222
+ count += 1
223
+ end
224
+ count.must_equal 12
225
+ end
226
+ it 'must clone properly' do
227
+ other = @stl.clone
228
+ idx = 0
229
+ while idx < @stl.size
230
+ @stl[idx].merge(extra: ' ').must_equal other[idx].merge(extra: ' ')
231
+ idx += 1
232
+ end
233
+ other.scale! 10
234
+ other.stats[:size][:z].must_equal 10
235
+ @stl.stats[:size][:z].must_equal 1
236
+ other.stats[:header].must_equal @stl.stats[:header]
237
+ end
238
+ it 'must have clone on-demand methods' do
239
+ @stl.scale(10).stats[:size][:x].must_equal 10
240
+ @stl.stats[:size][:x].must_equal 1
241
+
242
+ @stl.mirror(:x, :y).stats[:min][:z].must_equal(-1)
243
+ @stl.stats[:min][:z].must_equal 0
244
+
245
+ @stl.translate_relative(x: 5).stats[:min][:x].must_equal 5
246
+ @stl.stats[:min][:x].must_equal 0
247
+ end
248
+ it 'must have normal string representation' do
249
+ @stl.to_s.must_equal '#<RADMesh::STL header="solid admesh">'
250
+ end
251
+ end
252
+
253
+ describe 'when opening an non-existing file' do
254
+ it 'must blow up' do
255
+ proc { RADMesh::STL.new 'bad_filename.stl' }.must_raise IOError
256
+ end
257
+ end
258
+
259
+ describe 'when having an empty STL' do
260
+ it 'must initialize fine' do
261
+ RADMesh::STL.new
262
+ end
263
+ it 'must open merge fine' do
264
+ stl = RADMesh::STL.new
265
+ stl.open_merge! 'block.stl'
266
+ stl.stats[:size][:x].must_equal 1
267
+ end
268
+ end
269
+ end
metadata ADDED
@@ -0,0 +1,55 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: radmesh
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.98.1
5
+ platform: ruby
6
+ authors:
7
+ - Miro Hrončok
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-01-25 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: ! " ADMesh is a library for processing triangulated solid meshes.\n
14
+ \ Currently, ADMesh only reads the STL file format that is used\n for rapid
15
+ prototyping applications, although it can write STL,\n VRML, OFF, and DXF files.
16
+ Those are bindings for Ruby.\n You'll need the ADMesh C library in version 0.98.x.\n"
17
+ email: miro@hroncok.cz
18
+ executables: []
19
+ extensions: []
20
+ extra_rdoc_files: []
21
+ files:
22
+ - Gemfile
23
+ - LICENSE
24
+ - README.md
25
+ - Rakefile
26
+ - block.stl
27
+ - lib/cadmesh.rb
28
+ - lib/radmesh.rb
29
+ - radmesh.gemspec
30
+ - spec/radmesh_spec.rb
31
+ homepage: https://github.com/admesh/rubygem-admesh
32
+ licenses:
33
+ - GPL-2.0+
34
+ metadata: {}
35
+ post_install_message:
36
+ rdoc_options: []
37
+ require_paths:
38
+ - lib
39
+ required_ruby_version: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ required_rubygems_version: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ! '>='
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ requirements: []
50
+ rubyforge_project:
51
+ rubygems_version: 2.4.5
52
+ signing_key:
53
+ specification_version: 4
54
+ summary: Ruby wrapper around ADMesh
55
+ test_files: []