From 907c63e99227e3f2748e2ff38277ab56b7067fc6 Mon Sep 17 00:00:00 2001 From: aza Date: Fri, 13 Feb 2015 03:00:20 -0300 Subject: [PATCH] adding volume calculation --- lib/stl.rb | 11 +++++- lib/stl/face.rb | 13 +++++++ test/fixtures/box.stl | 86 +++++++++++++++++++++++++++++++++++++++++++ test/stl.rb | 13 +++++++ 4 files changed, 122 insertions(+), 1 deletion(-) create mode 100644 test/fixtures/box.stl diff --git a/lib/stl.rb b/lib/stl.rb index bb22ec9..4f6ab45 100644 --- a/lib/stl.rb +++ b/lib/stl.rb @@ -132,4 +132,13 @@ def translate(offset) def write(filename, format=:binary) self.class.write(filename, faces, format) end -end \ No newline at end of file + + # @return [Float] the volume in cube stl units (usually milimeters) + def volume + vol = 0 + faces.each do |face| + vol = vol + face.signed_volume + end + vol.abs + end +end diff --git a/lib/stl/face.rb b/lib/stl/face.rb index 75dad18..5873a2b 100644 --- a/lib/stl/face.rb +++ b/lib/stl/face.rb @@ -15,5 +15,18 @@ def initialize(normal, *vertices) @normal = normal @points = vertices end + + # @return [Float] The signed volume + def signed_volume + # math voodoo acording to: + # http://stackoverflow.com/questions/1406029/how-to-calculate-the-volume-of-a-3d-mesh-object-the-surface-of-which-is-made-up + v321 = @points[2][0] * @points[1][1] * @points[0][2] + v231 = @points[1][0] * @points[2][1] * @points[0][2] + v312 = @points[2][0] * @points[0][1] * @points[1][2] + v132 = @points[0][0] * @points[2][1] * @points[1][2] + v213 = @points[1][0] * @points[0][1] * @points[2][2] + v123 = @points[0][0] * @points[1][1] * @points[2][2] + (1.0/6.0)*(-v321 + v231 + v312 - v132 - v213 + v123) + end end end diff --git a/test/fixtures/box.stl b/test/fixtures/box.stl new file mode 100644 index 0000000..2b78f25 --- /dev/null +++ b/test/fixtures/box.stl @@ -0,0 +1,86 @@ +solid OpenSCAD_Model + facet normal -1 0 0 + outer loop + vertex -15 -10 10 + vertex -15 10 10 + vertex -15 -10 -10 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex -15 -10 -10 + vertex -15 10 10 + vertex -15 10 -10 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex -15 -10 10 + vertex 15 -10 10 + vertex 15 10 10 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex -15 10 10 + vertex -15 -10 10 + vertex 15 10 10 + endloop + endfacet + facet normal 0 -1 0 + outer loop + vertex -15 -10 -10 + vertex 15 -10 -10 + vertex 15 -10 10 + endloop + endfacet + facet normal 0 -1 0 + outer loop + vertex -15 -10 10 + vertex -15 -10 -10 + vertex 15 -10 10 + endloop + endfacet + facet normal 0 0 -1 + outer loop + vertex -15 10 -10 + vertex 15 10 -10 + vertex -15 -10 -10 + endloop + endfacet + facet normal 0 0 -1 + outer loop + vertex -15 -10 -10 + vertex 15 10 -10 + vertex 15 -10 -10 + endloop + endfacet + facet normal 0 1 0 + outer loop + vertex -15 10 10 + vertex 15 10 10 + vertex -15 10 -10 + endloop + endfacet + facet normal 0 1 0 + outer loop + vertex -15 10 -10 + vertex 15 10 10 + vertex 15 10 -10 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 15 -10 -10 + vertex 15 10 -10 + vertex 15 10 10 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 15 -10 10 + vertex 15 -10 -10 + vertex 15 10 10 + endloop + endfacet +endsolid OpenSCAD_Model diff --git a/test/stl.rb b/test/stl.rb index 8f6eb8e..b30ab3f 100644 --- a/test/stl.rb +++ b/test/stl.rb @@ -66,6 +66,19 @@ end end + describe 'when reading a box' do + subject { STL.read('test/fixtures/box.stl') } + + it 'face must have a signed volume' do + subject.faces.first.signed_volume.must_equal 1000.0 + end + + it 'must have a volume' do + subject.volume.must_equal 12000.0 + subject.scale(2).volume.must_equal 96000.0 + end + end + describe 'when reading from a binary file' do subject { STL.read('test/fixtures/binary_triangle.stl') }