triangular 0.0.1 → 0.0.2
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/README.rdoc +37 -4
- data/examples/slice_example.rb +7 -2
- data/lib/triangular.rb +1 -0
- data/lib/triangular/facet.rb +6 -0
- data/lib/triangular/line.rb +2 -2
- data/lib/triangular/point.rb +6 -0
- data/lib/triangular/polyline.rb +4 -4
- data/lib/triangular/solid.rb +47 -1
- data/lib/triangular/units.rb +30 -0
- data/lib/triangular/version.rb +1 -1
- data/lib/triangular/vertex.rb +1 -0
- data/spec/facet_spec.rb +22 -46
- data/spec/line_spec.rb +11 -93
- data/spec/point_spec.rb +21 -0
- data/spec/polyline_spec.rb +4 -4
- data/spec/solid_spec.rb +123 -0
- data/spec/units_spec.rb +75 -0
- metadata +4 -2
data/README.rdoc
CHANGED
@@ -7,25 +7,58 @@ The main purpose of Triangular is to enable its users to quickly create new soft
|
|
7
7
|
Please note that Triangular requires Ruby 1.9+. Triangular is currently in the Alpha stage of development which means that the API can and will change, and that new features will be added often!
|
8
8
|
|
9
9
|
=== A Quick Example
|
10
|
+
|
11
|
+
require "rubygems"
|
12
|
+
require "triangular"
|
10
13
|
|
11
14
|
# Open and parse an STL file
|
12
15
|
solid = Triangular.parse_file("test.stl")
|
13
16
|
|
14
|
-
#
|
15
|
-
|
17
|
+
# Set the units of measurement for the resulting solid to inches
|
18
|
+
solid.units = :inches
|
19
|
+
|
20
|
+
# Move the solid so that all of it's coordinates are in positive space (ie: greater than 0)
|
21
|
+
solid.align_to_origin!
|
22
|
+
|
23
|
+
# Get the bounding box of the solid
|
24
|
+
bounds = solid.get_bounds
|
25
|
+
|
26
|
+
# Create a section plane ('slice') through the solid on the XY plane at a Z height of 0.7
|
27
|
+
slice = solid.slice_at_z(0.7)
|
28
|
+
|
29
|
+
# Open a file for SVG output
|
30
|
+
File.open("slice.svg", "w+") do |file|
|
16
31
|
|
17
|
-
|
18
|
-
|
32
|
+
# Output the slice as an SVG document (correctly scaled according to the solid's units)
|
33
|
+
file.puts slice.to_svg(bounds[1].x, bounds[1].y, solid.units)
|
34
|
+
end
|
19
35
|
|
20
36
|
=== Installation
|
21
37
|
|
22
38
|
For ease of use the Triangular is packaged as a RubyGem. Providing you already have Ruby and RubyGems installing Triangular is as easy as entering the following command in a terminal:
|
23
39
|
|
24
40
|
gem install triangular
|
41
|
+
|
42
|
+
=== Performance
|
43
|
+
|
44
|
+
At the moment Triangular has not been optimized at all. The parser is a relatively naive one that was designed to be easy to read rather than performant. Once the feature-set of Triangular has stabilized I will be doing a pass over it in order to make it fast enough for production use. Right now it could definitely be improved.
|
45
|
+
|
46
|
+
For example here is some information about run-times when processing a 51Mb STL file:
|
47
|
+
|
48
|
+
solid = Triangular.parse("big_file.stl")
|
49
|
+
# 65 seconds
|
50
|
+
|
51
|
+
solid.align_to_origin!
|
52
|
+
# 8 seconds
|
53
|
+
|
54
|
+
solid.slice_at_z(1.0)
|
55
|
+
# 2 seconds
|
25
56
|
|
26
57
|
=== Author & Credits
|
27
58
|
|
28
59
|
Author:: {Aaron Gough}[mailto:aaron@aarongough.com]
|
29
60
|
|
61
|
+
Special thanks go out to {Alkas Baybas}[https://github.com/abaybas] for lending me his massive brain!
|
62
|
+
|
30
63
|
Copyright (c) 2011 {Aaron Gough}[http://thingsaaronmade.com/] ({thingsaaronmade.com}[http://thingsaaronmade.com/]), released under the MIT license
|
31
64
|
|
data/examples/slice_example.rb
CHANGED
@@ -2,8 +2,13 @@ require "bundler/setup"
|
|
2
2
|
require "triangular"
|
3
3
|
|
4
4
|
solid = Triangular.parse_file("#{File.dirname(__FILE__)}/example_files/y-axis-spacer.stl")
|
5
|
-
|
5
|
+
solid.units = :inches
|
6
|
+
|
7
|
+
solid.align_to_origin!
|
8
|
+
bounds = solid.get_bounds
|
9
|
+
|
10
|
+
polyline = solid.slice_at_z(0.7)
|
6
11
|
|
7
12
|
File.open(File.expand_path("~/Desktop/slice.svg"), "w+") do |file|
|
8
|
-
file.puts polyline.to_svg(
|
13
|
+
file.puts polyline.to_svg(bounds[1].x, bounds[1].y, solid.units)
|
9
14
|
end
|
data/lib/triangular.rb
CHANGED
data/lib/triangular/facet.rb
CHANGED
data/lib/triangular/line.rb
CHANGED
@@ -31,8 +31,8 @@ module Triangular
|
|
31
31
|
Point.new(x_intersect, y_intersect, z_plane)
|
32
32
|
end
|
33
33
|
|
34
|
-
def to_svg_path
|
35
|
-
"<path d=\"M #{@start.x} #{@start.y} L #{@end.x} #{@end.y}\" fill=\"none\" stroke=\"black\" stroke-width=\"
|
34
|
+
def to_svg_path(units)
|
35
|
+
"<path d=\"M #{@start.x} #{@start.y} L #{@end.x} #{@end.y}\" fill=\"none\" stroke=\"black\" stroke-width=\"#{Units.stroke_width(units)}\" />"
|
36
36
|
end
|
37
37
|
end
|
38
38
|
end
|
data/lib/triangular/point.rb
CHANGED
@@ -13,6 +13,12 @@ module Triangular
|
|
13
13
|
"#{@x.to_f} #{@y.to_f} #{@z.to_f}"
|
14
14
|
end
|
15
15
|
|
16
|
+
def translate!(x, y, z)
|
17
|
+
@x += x
|
18
|
+
@y += y
|
19
|
+
@z += z
|
20
|
+
end
|
21
|
+
|
16
22
|
def ==(other)
|
17
23
|
return false unless other.is_a?(Point)
|
18
24
|
self.x == other.x && self.y == other.y && self.z == other.z
|
data/lib/triangular/polyline.rb
CHANGED
@@ -7,14 +7,14 @@ module Triangular
|
|
7
7
|
@lines = lines
|
8
8
|
end
|
9
9
|
|
10
|
-
def to_svg(x_offset =
|
10
|
+
def to_svg(width, height, units, x_offset = 0, y_offset = 0)
|
11
11
|
output = '<?xml version="1.0" standalone="no"?>' + "\n"
|
12
12
|
output << '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">' + "\n"
|
13
|
-
output <<
|
14
|
-
output << " <g transform=\"translate(#{x_offset},#{y_offset})\">\n"
|
13
|
+
output << "<svg x=\"0\" y=\"0\" width=\"#{width}#{Units.svg_name(units)}\" height=\"#{height}#{Units.svg_name(units)}\" viewBox=\"0 0 #{width} #{height}\" xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">\n"
|
14
|
+
output << " <g transform=\"translate(#{x_offset}#{Units.svg_name(units)},#{y_offset}#{Units.svg_name(units)})\">\n"
|
15
15
|
|
16
16
|
@lines.each do |line|
|
17
|
-
output << " " + line.to_svg_path + "\n"
|
17
|
+
output << " " + line.to_svg_path(units) + "\n"
|
18
18
|
end
|
19
19
|
|
20
20
|
output << ' </g>' + "\n"
|
data/lib/triangular/solid.rb
CHANGED
@@ -1,11 +1,12 @@
|
|
1
1
|
module Triangular
|
2
2
|
class Solid
|
3
3
|
|
4
|
-
attr_accessor :name, :facets
|
4
|
+
attr_accessor :name, :facets, :units
|
5
5
|
|
6
6
|
def initialize(name, *args)
|
7
7
|
@name = name
|
8
8
|
@facets = args
|
9
|
+
@units = units
|
9
10
|
end
|
10
11
|
|
11
12
|
def to_s
|
@@ -24,6 +25,45 @@ module Triangular
|
|
24
25
|
output
|
25
26
|
end
|
26
27
|
|
28
|
+
def get_bounds
|
29
|
+
largest_x = @facets[0].vertices[0].x
|
30
|
+
largest_y = @facets[0].vertices[0].y
|
31
|
+
largest_z = @facets[0].vertices[0].z
|
32
|
+
|
33
|
+
smallest_x = @facets[0].vertices[0].x
|
34
|
+
smallest_y = @facets[0].vertices[0].y
|
35
|
+
smallest_z = @facets[0].vertices[0].z
|
36
|
+
|
37
|
+
@facets.each do |facet|
|
38
|
+
facet.vertices.each do |vertex|
|
39
|
+
largest_x = vertex.x if vertex.x > largest_x
|
40
|
+
largest_y = vertex.y if vertex.y > largest_y
|
41
|
+
largest_z = vertex.z if vertex.z > largest_z
|
42
|
+
|
43
|
+
smallest_x = vertex.x if vertex.x < smallest_x
|
44
|
+
smallest_y = vertex.y if vertex.y < smallest_y
|
45
|
+
smallest_z = vertex.z if vertex.z < smallest_z
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
[Point.new(smallest_x, smallest_y, smallest_z), Point.new(largest_x, largest_y, largest_z)]
|
50
|
+
end
|
51
|
+
|
52
|
+
def align_to_origin!
|
53
|
+
bounds = self.get_bounds
|
54
|
+
self.translate!(-bounds[0].x, -bounds[0].y, -bounds[0].z)
|
55
|
+
end
|
56
|
+
|
57
|
+
def center!
|
58
|
+
bounds = self.get_bounds
|
59
|
+
|
60
|
+
x_translation = ((bounds[1].x - bounds[0].x).abs / 2) + -bounds[1].x
|
61
|
+
y_translation = ((bounds[1].y - bounds[0].y).abs / 2) + -bounds[1].y
|
62
|
+
z_translation = ((bounds[1].z - bounds[0].z).abs / 2) + -bounds[1].z
|
63
|
+
|
64
|
+
self.translate!(x_translation, y_translation, z_translation)
|
65
|
+
end
|
66
|
+
|
27
67
|
def slice_at_z(z_plane)
|
28
68
|
lines = @facets.map {|facet| facet.intersection_at_z(z_plane) }
|
29
69
|
lines.compact!
|
@@ -31,6 +71,12 @@ module Triangular
|
|
31
71
|
Polyline.new(lines)
|
32
72
|
end
|
33
73
|
|
74
|
+
def translate!(x, y, z)
|
75
|
+
@facets.each do |facet|
|
76
|
+
facet.translate!(x, y, z)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
34
80
|
def self.parse(string)
|
35
81
|
partial_pattern = /\s* solid\s+ (?<name> [a-zA-Z0-9\-\_\.]+)?/x
|
36
82
|
match_data = string.match(partial_pattern)
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
|
3
|
+
module Triangular
|
4
|
+
class Units
|
5
|
+
|
6
|
+
UNITS = {
|
7
|
+
:inches => {:name => 'inches', :svg_name => 'in', :stroke_width => 0.005},
|
8
|
+
:centimeters => {:name => 'centimeters', :svg_name => 'cm', :stroke_width => 0.01},
|
9
|
+
:millimeters => {:name => 'millimeters', :svg_name => 'mm', :stroke_width => 0.1},
|
10
|
+
:none => {:name => 'none', :svg_name => '', :stroke_width => 0.1}
|
11
|
+
}
|
12
|
+
|
13
|
+
def self.get_property(unit, name)
|
14
|
+
raise "Unknown unit: #{unit}" unless UNITS.has_key?(unit)
|
15
|
+
UNITS[unit][name]
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.name(unit)
|
19
|
+
self.get_property(unit, :name)
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.svg_name(unit)
|
23
|
+
self.get_property(unit, :svg_name)
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.stroke_width(unit)
|
27
|
+
self.get_property(unit, :stroke_width)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/lib/triangular/version.rb
CHANGED
data/lib/triangular/vertex.rb
CHANGED
data/spec/facet_spec.rb
CHANGED
@@ -154,52 +154,6 @@ describe Facet do
|
|
154
154
|
end
|
155
155
|
end
|
156
156
|
|
157
|
-
context "for a facet that intersects the target Z plane at an angle" do
|
158
|
-
before do
|
159
|
-
vertex1 = Vertex.new(0.0, 0.0, 0.0)
|
160
|
-
vertex2 = Vertex.new(0.0, 6.0, 6.0)
|
161
|
-
vertex3 = Vertex.new(6.0, 6.0, 6.0)
|
162
|
-
|
163
|
-
@facet = Facet.new(nil, vertex1, vertex2, vertex3)
|
164
|
-
end
|
165
|
-
|
166
|
-
context "when the target Z plane is 3.0" do
|
167
|
-
it "should return a line object" do
|
168
|
-
@facet.intersection_at_z(3.0).should be_a Line
|
169
|
-
end
|
170
|
-
|
171
|
-
it "should return a line with the correct start value" do
|
172
|
-
@facet.intersection_at_z(3.0).start.x.should == 0.0
|
173
|
-
@facet.intersection_at_z(3.0).start.y.should == 3.0
|
174
|
-
@facet.intersection_at_z(3.0).start.z.should == 3.0
|
175
|
-
end
|
176
|
-
|
177
|
-
it "should return a line with the correct end value" do
|
178
|
-
@facet.intersection_at_z(3.0).end.x.should == 3.0
|
179
|
-
@facet.intersection_at_z(3.0).end.y.should == 3.0
|
180
|
-
@facet.intersection_at_z(3.0).end.z.should == 3.0
|
181
|
-
end
|
182
|
-
end
|
183
|
-
|
184
|
-
context "when the target Z plane is 6.0" do
|
185
|
-
it "should return a line object" do
|
186
|
-
@facet.intersection_at_z(6.0).should be_a Line
|
187
|
-
end
|
188
|
-
|
189
|
-
it "should return a line with the correct start value" do
|
190
|
-
@facet.intersection_at_z(6.0).start.x.should == 0.0
|
191
|
-
@facet.intersection_at_z(6.0).start.y.should == 6.0
|
192
|
-
@facet.intersection_at_z(6.0).start.z.should == 6.0
|
193
|
-
end
|
194
|
-
|
195
|
-
it "should return a line with the correct end value" do
|
196
|
-
@facet.intersection_at_z(6.0).end.x.should == 6.0
|
197
|
-
@facet.intersection_at_z(6.0).end.y.should == 6.0
|
198
|
-
@facet.intersection_at_z(6.0).end.z.should == 6.0
|
199
|
-
end
|
200
|
-
end
|
201
|
-
end
|
202
|
-
|
203
157
|
context "with vertices in both positive and negative space" do
|
204
158
|
before do
|
205
159
|
@facet = Facet.parse(<<-EOD)
|
@@ -254,4 +208,26 @@ describe Facet do
|
|
254
208
|
end
|
255
209
|
end
|
256
210
|
end
|
211
|
+
|
212
|
+
describe "#translate!" do
|
213
|
+
before do
|
214
|
+
@facet = Facet.parse(<<-EOD)
|
215
|
+
facet normal 0.0 0.0 -1.0
|
216
|
+
outer loop
|
217
|
+
vertex -16.5 0.0 -0.75
|
218
|
+
vertex 0.0 -9.5 -0.75
|
219
|
+
vertex 0.0 0.0 -0.75
|
220
|
+
endloop
|
221
|
+
endfacet
|
222
|
+
EOD
|
223
|
+
end
|
224
|
+
|
225
|
+
it "should call translate on each of it's Vertices" do
|
226
|
+
@facet.vertices[0].should_receive(:translate!).with(16.5, 9.5, 0.75)
|
227
|
+
@facet.vertices[1].should_receive(:translate!).with(16.5, 9.5, 0.75)
|
228
|
+
@facet.vertices[2].should_receive(:translate!).with(16.5, 9.5, 0.75)
|
229
|
+
|
230
|
+
@facet.translate!(16.5, 9.5, 0.75)
|
231
|
+
end
|
232
|
+
end
|
257
233
|
end
|
data/spec/line_spec.rb
CHANGED
@@ -37,115 +37,33 @@ describe Line do
|
|
37
37
|
|
38
38
|
describe "#intersection_at_z" do
|
39
39
|
context "for a line that intersects the target Z plane" do
|
40
|
-
context "and
|
40
|
+
context "and spans both positive and negative space" do
|
41
41
|
context "with a positive Z vector" do
|
42
42
|
before do
|
43
|
-
@line = Line.new(Vertex.new(
|
44
|
-
end
|
45
|
-
|
46
|
-
it "should return a a Point" do
|
47
|
-
@line.intersection_at_z(3.0).should be_a Point
|
43
|
+
@line = Line.new(Vertex.new(-1.0, 1.0, 1.0), Vertex.new(1.0, 1.0, -1.0))
|
48
44
|
end
|
49
45
|
|
50
46
|
it "should return a Point representing the intersection" do
|
51
|
-
@line.intersection_at_z(
|
52
|
-
@line.intersection_at_z(
|
53
|
-
@line.intersection_at_z(
|
47
|
+
@line.intersection_at_z(0).x.should == 0.0
|
48
|
+
@line.intersection_at_z(0).y.should == 1.0
|
49
|
+
@line.intersection_at_z(0).z.should == 0.0
|
54
50
|
end
|
55
51
|
end
|
56
52
|
|
57
53
|
context "with a negative Z vector" do
|
58
54
|
before do
|
59
|
-
@line = Line.new(Vertex.new(
|
55
|
+
@line = Line.new(Vertex.new(1.0, 1.0, 1.0), Vertex.new(-1.0, -1.0, -1.0))
|
60
56
|
end
|
61
57
|
|
62
58
|
it "should return a Point representing the intersection" do
|
63
|
-
@line.intersection_at_z(
|
64
|
-
@line.intersection_at_z(
|
65
|
-
@line.intersection_at_z(
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
context "and is located away from the origin" do
|
71
|
-
context "with a positive Z vector" do
|
72
|
-
before do
|
73
|
-
@line = Line.new(Vertex.new(7.0, 7.0, 1.0), Vertex.new(7.0, 7.0, 7.0))
|
74
|
-
end
|
75
|
-
|
76
|
-
it "should return a Point representing the intersection" do
|
77
|
-
@line.intersection_at_z(4.0).x.should == 7.0
|
78
|
-
@line.intersection_at_z(4.0).y.should == 7.0
|
79
|
-
@line.intersection_at_z(4.0).z.should == 4.0
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
context "with a negative Z vector" do
|
84
|
-
before do
|
85
|
-
@line = Line.new(Vertex.new(7.0, 7.0, 7.0), Vertex.new(1.0, 1.0, 1.0))
|
86
|
-
end
|
87
|
-
|
88
|
-
it "should return a Point representing the intersection" do
|
89
|
-
@line.intersection_at_z(4.0).x.should == 4.0
|
90
|
-
@line.intersection_at_z(4.0).y.should == 4.0
|
91
|
-
@line.intersection_at_z(4.0).z.should == 4.0
|
59
|
+
@line.intersection_at_z(0).x.should == 0
|
60
|
+
@line.intersection_at_z(0).y.should == 0
|
61
|
+
@line.intersection_at_z(0).z.should == 0
|
92
62
|
end
|
93
63
|
end
|
94
64
|
end
|
95
65
|
end
|
96
|
-
|
97
|
-
context "and is located in negative space" do
|
98
|
-
context "with a negative Z vector" do
|
99
|
-
before do
|
100
|
-
@line = Line.new(Vertex.new(-1.0, -1.0, -1.0), Vertex.new(-7.0, -7.0, -7.0))
|
101
|
-
end
|
102
|
-
|
103
|
-
it "should return a Point representing the intersection" do
|
104
|
-
@line.intersection_at_z(-4.0).x.should == -4.0
|
105
|
-
@line.intersection_at_z(-4.0).y.should == -4.0
|
106
|
-
@line.intersection_at_z(-4.0).z.should == -4.0
|
107
|
-
end
|
108
|
-
end
|
109
|
-
|
110
|
-
context "with a positive Z vector" do
|
111
|
-
before do
|
112
|
-
@line = Line.new(Vertex.new(-7.0, -7.0, -7.0), Vertex.new(-1.0, -1.0, -1.0))
|
113
|
-
end
|
114
|
-
|
115
|
-
it "should return a Point representing the intersection" do
|
116
|
-
@line.intersection_at_z(-4.0).x.should == -4.0
|
117
|
-
@line.intersection_at_z(-4.0).y.should == -4.0
|
118
|
-
@line.intersection_at_z(-4.0).z.should == -4.0
|
119
|
-
end
|
120
|
-
end
|
121
|
-
end
|
122
|
-
|
123
|
-
context "and spans both positive and negative space" do
|
124
|
-
context "with a positive Z vector" do
|
125
|
-
before do
|
126
|
-
@line = Line.new(Vertex.new(-1.0, 1.0, 1.0), Vertex.new(1.0, 1.0, -1.0))
|
127
|
-
end
|
128
|
-
|
129
|
-
it "should return a Point representing the intersection" do
|
130
|
-
@line.intersection_at_z(0).x.should == 0.0
|
131
|
-
@line.intersection_at_z(0).y.should == 1.0
|
132
|
-
@line.intersection_at_z(0).z.should == 0.0
|
133
|
-
end
|
134
|
-
end
|
135
66
|
|
136
|
-
context "with a negative Z vector" do
|
137
|
-
before do
|
138
|
-
@line = Line.new(Vertex.new(1.0, 1.0, 1.0), Vertex.new(-1.0, -1.0, -1.0))
|
139
|
-
end
|
140
|
-
|
141
|
-
it "should return a Point representing the intersection" do
|
142
|
-
@line.intersection_at_z(0).x.should == 0
|
143
|
-
@line.intersection_at_z(0).y.should == 0
|
144
|
-
@line.intersection_at_z(0).z.should == 0
|
145
|
-
end
|
146
|
-
end
|
147
|
-
end
|
148
|
-
|
149
67
|
context "for a line that lies on the target Z plane" do
|
150
68
|
before do
|
151
69
|
@line = Line.new(Vertex.new(0.0, 0.0, 3.0), Vertex.new(0.0, 6.0, 3.0))
|
@@ -182,9 +100,9 @@ describe Line do
|
|
182
100
|
describe "#to_svg_path" do
|
183
101
|
it "should return a string containing an SVG path" do
|
184
102
|
line = Line.new(Vertex.new(0.0, 0.0, 0.0), Vertex.new(1.0, 1.0, 1.0))
|
185
|
-
expected_output = '<path d="M 0.0 0.0 L 1.0 1.0" fill="none" stroke="black" stroke-width="
|
103
|
+
expected_output = '<path d="M 0.0 0.0 L 1.0 1.0" fill="none" stroke="black" stroke-width="0.005" />'
|
186
104
|
|
187
|
-
line.to_svg_path.should == expected_output
|
105
|
+
line.to_svg_path(:inches).should == expected_output
|
188
106
|
end
|
189
107
|
end
|
190
108
|
end
|
data/spec/point_spec.rb
CHANGED
@@ -64,4 +64,25 @@ describe Point do
|
|
64
64
|
(Point.new(1.0, 2.0, -3.1) == Point.new(1.0, 2.0, -3.2)).should be_false
|
65
65
|
end
|
66
66
|
end
|
67
|
+
|
68
|
+
describe "#translate!" do
|
69
|
+
before do
|
70
|
+
@point = Point.new(1.0, 1.0, 1.0)
|
71
|
+
end
|
72
|
+
|
73
|
+
it "should add the supplied value to X" do
|
74
|
+
@point.translate!(16.5, 9.5, 0.75)
|
75
|
+
@point.x.should == 17.5
|
76
|
+
end
|
77
|
+
|
78
|
+
it "should add the supplied value to Y" do
|
79
|
+
@point.translate!(16.5, 9.5, 0.75)
|
80
|
+
@point.y.should == 10.5
|
81
|
+
end
|
82
|
+
|
83
|
+
it "should add the supplied value to Z" do
|
84
|
+
@point.translate!(16.5, 9.5, 0.75)
|
85
|
+
@point.z.should == 1.75
|
86
|
+
end
|
87
|
+
end
|
67
88
|
end
|
data/spec/polyline_spec.rb
CHANGED
@@ -8,13 +8,13 @@ describe Polyline do
|
|
8
8
|
|
9
9
|
expected_svg = '<?xml version="1.0" standalone="no"?>' + "\n"
|
10
10
|
expected_svg += '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">' + "\n"
|
11
|
-
expected_svg += '<svg xmlns="http://www.w3.org/2000/svg" version="1.1">' + "\n"
|
12
|
-
expected_svg += ' <g transform="translate(
|
13
|
-
expected_svg += " #{line.to_svg_path}\n"
|
11
|
+
expected_svg += '<svg x="0" y="0" width="20in" height="30in" viewBox="0 0 20 30" xmlns="http://www.w3.org/2000/svg" version="1.1">' + "\n"
|
12
|
+
expected_svg += ' <g transform="translate(1in,2in)">' + "\n"
|
13
|
+
expected_svg += " #{line.to_svg_path(:inches)}\n"
|
14
14
|
expected_svg += ' </g>' + "\n"
|
15
15
|
expected_svg += '</svg>'
|
16
16
|
|
17
|
-
polyline.to_svg(
|
17
|
+
polyline.to_svg(20, 30, :inches, 1, 2).should == expected_svg
|
18
18
|
end
|
19
19
|
end
|
20
20
|
end
|
data/spec/solid_spec.rb
CHANGED
@@ -79,7 +79,130 @@ describe Solid do
|
|
79
79
|
it "should return a Polyline" do
|
80
80
|
@solid.slice_at_z(0).should be_a Polyline
|
81
81
|
end
|
82
|
+
end
|
83
|
+
|
84
|
+
describe "#get_bounds" do
|
85
|
+
before do
|
86
|
+
@solid = Solid.parse(<<-EOD)
|
87
|
+
solid y-axis-spacer
|
88
|
+
facet normal 0.0 0.0 -1.0
|
89
|
+
outer loop
|
90
|
+
vertex -16.5 0.0 -0.75
|
91
|
+
vertex 0.0 -9.5 -0.75
|
92
|
+
vertex 0.0 0.0 -0.75
|
93
|
+
endloop
|
94
|
+
endfacet
|
95
|
+
facet normal -0.0 1.0 0.0
|
96
|
+
outer loop
|
97
|
+
vertex 0.0 -1.87 0.0
|
98
|
+
vertex 16.5 -1.87 -0.13
|
99
|
+
vertex 0.0 1.87 -0.13
|
100
|
+
endloop
|
101
|
+
endfacet
|
102
|
+
endsolid y-axis-spacer
|
103
|
+
EOD
|
104
|
+
end
|
105
|
+
|
106
|
+
it "should return an array" do
|
107
|
+
@solid.get_bounds.should be_a Array
|
108
|
+
end
|
109
|
+
|
110
|
+
it "should return a point with the smallest bounds" do
|
111
|
+
@solid.get_bounds[0].x.should == -16.5
|
112
|
+
@solid.get_bounds[0].y.should == -9.5
|
113
|
+
@solid.get_bounds[0].z.should == -0.75
|
114
|
+
end
|
82
115
|
|
116
|
+
it "should return a point with the largest bounds" do
|
117
|
+
@solid.get_bounds[1].x.should == 16.5
|
118
|
+
@solid.get_bounds[1].y.should == 1.87
|
119
|
+
@solid.get_bounds[1].z.should == 0.0
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
describe "#translate!" do
|
124
|
+
before do
|
125
|
+
@solid = Solid.parse(<<-EOD)
|
126
|
+
solid y-axis-spacer
|
127
|
+
facet normal 0.0 0.0 -1.0
|
128
|
+
outer loop
|
129
|
+
vertex -16.5 0.0 -0.75
|
130
|
+
vertex 0.0 -9.5 -0.75
|
131
|
+
vertex 0.0 0.0 -0.75
|
132
|
+
endloop
|
133
|
+
endfacet
|
134
|
+
facet normal -0.0 1.0 0.0
|
135
|
+
outer loop
|
136
|
+
vertex 0.0 -1.87 0.0
|
137
|
+
vertex 16.5 -1.87 -0.13
|
138
|
+
vertex 0.0 1.87 -0.13
|
139
|
+
endloop
|
140
|
+
endfacet
|
141
|
+
endsolid y-axis-spacer
|
142
|
+
EOD
|
143
|
+
end
|
83
144
|
|
145
|
+
it "should call translate on each of it's Facets" do
|
146
|
+
@solid.facets[0].should_receive(:translate!).with(16.5, 9.5, 0.75)
|
147
|
+
@solid.facets[1].should_receive(:translate!).with(16.5, 9.5, 0.75)
|
148
|
+
|
149
|
+
@solid.translate!(16.5, 9.5, 0.75)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
describe "#align_to_origin!" do
|
154
|
+
before do
|
155
|
+
@solid = Solid.parse(<<-EOD)
|
156
|
+
solid y-axis-spacer
|
157
|
+
facet normal 0.0 0.0 -1.0
|
158
|
+
outer loop
|
159
|
+
vertex -16.5 0.0 5.0
|
160
|
+
vertex 0.0 -9.5 10.0
|
161
|
+
vertex 0.0 0.0 5.0
|
162
|
+
endloop
|
163
|
+
endfacet
|
164
|
+
facet normal -0.0 1.0 0.0
|
165
|
+
outer loop
|
166
|
+
vertex 0.0 -1.87 5.0
|
167
|
+
vertex 16.5 -1.87 11.0
|
168
|
+
vertex 0.0 1.87 6.0
|
169
|
+
endloop
|
170
|
+
endfacet
|
171
|
+
endsolid y-axis-spacer
|
172
|
+
EOD
|
173
|
+
end
|
174
|
+
|
175
|
+
it "should translate solid so the lowermost XYZ edges are all 0.0" do
|
176
|
+
@solid.should_receive(:translate!).with(16.5, 9.5, -5.0)
|
177
|
+
@solid.align_to_origin!
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
describe "#center!" do
|
182
|
+
before do
|
183
|
+
@solid = Solid.parse(<<-EOD)
|
184
|
+
solid y-axis-spacer
|
185
|
+
facet normal 0.0 0.0 -1.0
|
186
|
+
outer loop
|
187
|
+
vertex -16.5 0.0 5.0
|
188
|
+
vertex 0.0 -9.5 10.0
|
189
|
+
vertex 0.0 0.0 5.0
|
190
|
+
endloop
|
191
|
+
endfacet
|
192
|
+
facet normal -0.0 1.0 0.0
|
193
|
+
outer loop
|
194
|
+
vertex 0.0 -1.87 5.0
|
195
|
+
vertex 17.5 -1.87 11.0
|
196
|
+
vertex 0.0 1.5 6.0
|
197
|
+
endloop
|
198
|
+
endfacet
|
199
|
+
endsolid y-axis-spacer
|
200
|
+
EOD
|
201
|
+
end
|
202
|
+
|
203
|
+
it "should translate solid so the lowermost XYZ edges are all 0.0" do
|
204
|
+
@solid.should_receive(:translate!).with(-0.5, 4.0, -8.0)
|
205
|
+
@solid.center!
|
206
|
+
end
|
84
207
|
end
|
85
208
|
end
|
data/spec/units_spec.rb
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Units do
|
4
|
+
describe ".name" do
|
5
|
+
it "should return 'inches' for :inches" do
|
6
|
+
Units.name(:inches).should == 'inches'
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should return 'centimeters' for :centimeters" do
|
10
|
+
Units.name(:centimeters).should == 'centimeters'
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should return 'millimeters' for :millimeters" do
|
14
|
+
Units.name(:millimeters).should == 'millimeters'
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should return 'none' for :none" do
|
18
|
+
Units.name(:none).should == 'none'
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should raise an exception if called with an unknown unit" do
|
22
|
+
lambda {
|
23
|
+
Units.name(:error)
|
24
|
+
}.should raise_error
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe ".svg_name" do
|
29
|
+
it "should return 'in' for :inches" do
|
30
|
+
Units.svg_name(:inches).should == 'in'
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should return 'cm' for :centimeters" do
|
34
|
+
Units.svg_name(:centimeters).should == 'cm'
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should return 'mm' for :millimeters" do
|
38
|
+
Units.svg_name(:millimeters).should == 'mm'
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should return '' for :none" do
|
42
|
+
Units.svg_name(:none).should == ''
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should raise an exception if called with an unknown unit" do
|
46
|
+
lambda {
|
47
|
+
Units.svg_name(:error)
|
48
|
+
}.should raise_error
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe ".stroke_width" do
|
53
|
+
it "should return 'in' for :inches" do
|
54
|
+
Units.stroke_width(:inches).should == 0.005
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should return 'cm' for :centimeters" do
|
58
|
+
Units.stroke_width(:centimeters).should == 0.01
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should return 'mm' for :millimeters" do
|
62
|
+
Units.stroke_width(:millimeters).should == 0.1
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should return '' for :none" do
|
66
|
+
Units.stroke_width(:none).should == 0.1
|
67
|
+
end
|
68
|
+
|
69
|
+
it "should raise an exception if called with an unknown unit" do
|
70
|
+
lambda {
|
71
|
+
Units.stroke_width(:error)
|
72
|
+
}.should raise_error
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: triangular
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.0.
|
5
|
+
version: 0.0.2
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Aaron Gough
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2011-10-
|
13
|
+
date: 2011-10-19 00:00:00 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: bundler
|
@@ -59,6 +59,7 @@ files:
|
|
59
59
|
- lib/triangular/point.rb
|
60
60
|
- lib/triangular/polyline.rb
|
61
61
|
- lib/triangular/solid.rb
|
62
|
+
- lib/triangular/units.rb
|
62
63
|
- lib/triangular/vector.rb
|
63
64
|
- lib/triangular/version.rb
|
64
65
|
- lib/triangular/vertex.rb
|
@@ -71,6 +72,7 @@ files:
|
|
71
72
|
- spec/solid_spec.rb
|
72
73
|
- spec/spec_helper.rb
|
73
74
|
- spec/triangular_spec.rb
|
75
|
+
- spec/units_spec.rb
|
74
76
|
- spec/vertex_spec.rb
|
75
77
|
- triangular.gemspec
|
76
78
|
homepage: http://rubygems.org/gems/triangular
|