xrvg 0.0.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/LICENCE +21 -0
- data/README +88 -0
- data/Rakefile +263 -0
- data/examples/foreach.rb +9 -0
- data/examples/hellocrown.rb +7 -0
- data/examples/hellocrown2.rb +7 -0
- data/examples/hellocrownrecurse.rb +9 -0
- data/examples/helloworld.rb +5 -0
- data/examples/helloworldcompact.rb +5 -0
- data/examples/helloworldexpanded.rb +5 -0
- data/examples/palette_circle.rb +10 -0
- data/examples/sample.rb +10 -0
- data/examples/uplets.rb +9 -0
- data/lib/assertion.rb +14 -0
- data/lib/attributable.rb +152 -0
- data/lib/color.rb +295 -0
- data/lib/frame.rb +32 -0
- data/lib/geometry2D.rb +207 -0
- data/lib/interpolation.rb +59 -0
- data/lib/render.rb +269 -0
- data/lib/samplation.rb +416 -0
- data/lib/shape.rb +338 -0
- data/lib/style.rb +74 -0
- data/lib/trace.rb +28 -0
- data/lib/utils.rb +404 -0
- data/lib/xrvg.rb +37 -0
- data/test/test_attributable.rb +24 -0
- data/test/test_color.rb +79 -0
- data/test/test_frame.rb +12 -0
- data/test/test_geometry2D.rb +76 -0
- data/test/test_render.rb +18 -0
- data/test/test_style.rb +16 -0
- data/test/test_utils.rb +207 -0
- metadata +80 -0
data/lib/utils.rb
ADDED
@@ -0,0 +1,404 @@
|
|
1
|
+
#
|
2
|
+
# Several Ruby base class extensions
|
3
|
+
#
|
4
|
+
# Please also refer to the following link[http://xrvg.rubyforge.org/], and more particularly this[http://xrvg.rubyforge.org/RubyXRVGExtension.html], for
|
5
|
+
# further details.
|
6
|
+
#
|
7
|
+
# This contains :
|
8
|
+
# - +Range+ extension
|
9
|
+
# - +Array+ extension
|
10
|
+
|
11
|
+
require 'enumerator'
|
12
|
+
require 'trace'
|
13
|
+
require 'samplation'
|
14
|
+
require 'assertion'
|
15
|
+
|
16
|
+
#
|
17
|
+
# Extend class Range with module Samplable and other utilitary methods
|
18
|
+
# = Intro
|
19
|
+
# Range class is used in XRVG as a continuous 1D float interval.
|
20
|
+
# See this[http://xrvg.rubyforge.org/RubyXRVGExtension.html] for presentation
|
21
|
+
# = Use
|
22
|
+
# (0.0..1.0).rand
|
23
|
+
# (0.0..1.0).middle # => 0.5
|
24
|
+
# (0.0..2.0).sample(0.3) # => 0.6
|
25
|
+
# (0.0..1.0).samples( 3 ) {|v| puts v} # => "0.0" "0.5" "1.0"
|
26
|
+
#
|
27
|
+
class Range
|
28
|
+
|
29
|
+
# constant for (0.0..1.0) range
|
30
|
+
#
|
31
|
+
# must be used only as const (else use Range.O)
|
32
|
+
O = (0.0..1.0)
|
33
|
+
|
34
|
+
# constant for Angle range
|
35
|
+
#
|
36
|
+
# must be used only as const (else use Range.Angle)
|
37
|
+
Angle = (0.0..2.0*Math::PI)
|
38
|
+
|
39
|
+
# return unitary range, that is
|
40
|
+
# (0.0..1.0)
|
41
|
+
def Range.O
|
42
|
+
return Range::O.clone
|
43
|
+
end
|
44
|
+
|
45
|
+
# return angle range, that is
|
46
|
+
# (0.0..2.0*Math::PI)
|
47
|
+
def Range.Angle
|
48
|
+
return Range::Angle.clone
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
# compute the symetric of value in context of range
|
53
|
+
# (0.0..1.0).complement( 0.3 ) => 0.7
|
54
|
+
def complement( value )
|
55
|
+
diff = value - self.begin
|
56
|
+
return (self.end - value)
|
57
|
+
end
|
58
|
+
|
59
|
+
|
60
|
+
# -------------------------------------------------------------
|
61
|
+
# Samplable interface include and overriding
|
62
|
+
# -------------------------------------------------------------
|
63
|
+
include Samplable
|
64
|
+
include Splittable
|
65
|
+
|
66
|
+
# Range base FloatFunctor overloading to do
|
67
|
+
# (1.0..2.0).sample( 0.3 ) => 1.3
|
68
|
+
# (1.0..2.0).samples( 3 ) => [1.0, 1.5, 2.0]
|
69
|
+
def transform( value )
|
70
|
+
return (self.begin + ( self.end - self.begin ) * value)
|
71
|
+
end
|
72
|
+
|
73
|
+
# to speed up samplation on ranges, as used everywhere
|
74
|
+
def generate( nsamples ) #:nodoc:
|
75
|
+
result = []
|
76
|
+
if nsamples == 1
|
77
|
+
result = [0.0]
|
78
|
+
else
|
79
|
+
(nsamples).times {|i| result.push( i.to_f / (nsamples-1) )}
|
80
|
+
end
|
81
|
+
return result
|
82
|
+
end
|
83
|
+
|
84
|
+
# apply_sample is good by default
|
85
|
+
# apply_split is good by default
|
86
|
+
|
87
|
+
# size of the range
|
88
|
+
# (0.0..2.0).size => 2.0
|
89
|
+
def size
|
90
|
+
return self.end - self.begin
|
91
|
+
end
|
92
|
+
|
93
|
+
# returns a reversed range
|
94
|
+
# (1.0..2.0).reverse => (2.0..1.0)
|
95
|
+
def reverse
|
96
|
+
return Range.new( self.end, self.begin )
|
97
|
+
end
|
98
|
+
|
99
|
+
# resize range by factor, with fixed point center of the range
|
100
|
+
# (1.0..2.0).resize( 0.5 ) => (1.25..1.75)
|
101
|
+
def resize( factor )
|
102
|
+
center = self.sample( 0.5 )
|
103
|
+
halfsize = self.size / 2.0
|
104
|
+
newhalfsize = halfsize * factor
|
105
|
+
return (center - newhalfsize .. center + newhalfsize)
|
106
|
+
end
|
107
|
+
|
108
|
+
# mean value of the range (equiv to sample( 0.5 ))
|
109
|
+
# -> define in Samplable
|
110
|
+
# def mean()
|
111
|
+
# return self.sample( 0.5 )
|
112
|
+
# end
|
113
|
+
|
114
|
+
# alias mean as middle, as sample( 0.5 )
|
115
|
+
# -> define in Samplable
|
116
|
+
# alias middle mean
|
117
|
+
|
118
|
+
# return range with previous begin as new middle
|
119
|
+
# (1.0..2.0).sym => (0.0..2.0)
|
120
|
+
def sym()
|
121
|
+
return (self.begin - (self.end - self.begin ) .. self.end )
|
122
|
+
end
|
123
|
+
|
124
|
+
# return range with previous end as new middle
|
125
|
+
# (1.0..2.0).symend => (1.0..3.0)
|
126
|
+
def symend()
|
127
|
+
return (self.begin .. self.end + (self.end - self.begin ) )
|
128
|
+
end
|
129
|
+
|
130
|
+
# inverse function of .sample
|
131
|
+
# (1.0..2.0).abscissa( 0.3 ) => 1.3
|
132
|
+
def abscissa( value )
|
133
|
+
return (value - self.begin) / (self.end - self.begin)
|
134
|
+
end
|
135
|
+
|
136
|
+
# return a new range with boundaries translated of "value"
|
137
|
+
# (1.0..2.0).translate( -1.0 ) => (0.0..1.0)
|
138
|
+
def translate( value )
|
139
|
+
return (self.begin + value..self.end + value)
|
140
|
+
end
|
141
|
+
|
142
|
+
end
|
143
|
+
|
144
|
+
#
|
145
|
+
# Array extension to synchronize enumerations, and also provide other recurrent services
|
146
|
+
# See this[http://xrvg.rubyforge.org/RubyXRVGExtension.html] for presentation
|
147
|
+
#
|
148
|
+
class Array
|
149
|
+
|
150
|
+
# take only the nieme elements
|
151
|
+
#
|
152
|
+
# Experimental
|
153
|
+
# [1, 2, 3, 4].sub(2) => [1, 3]
|
154
|
+
def sub(period, &block)
|
155
|
+
result = []
|
156
|
+
self.foreach(period) do |slice|
|
157
|
+
item = slice[0]
|
158
|
+
if block
|
159
|
+
yield item
|
160
|
+
else
|
161
|
+
result.push( item )
|
162
|
+
end
|
163
|
+
end
|
164
|
+
return result
|
165
|
+
end
|
166
|
+
|
167
|
+
# return the sum of the elements of the Array
|
168
|
+
# works for array whose content defines the + operator
|
169
|
+
# [1.0, 2.0].sum => 3.0
|
170
|
+
# [Vector[-1.0,-1.0], Vector[1.0,1.0]].sum => Vector[0.0,0.0]
|
171
|
+
# [curve1, curve2].sum => concatenation of curves
|
172
|
+
def sum
|
173
|
+
sum = self[0]
|
174
|
+
self[1..-1].each {|v| sum += v}
|
175
|
+
return sum
|
176
|
+
end
|
177
|
+
|
178
|
+
# returns the mean of the array content
|
179
|
+
# [Vector[0.0,0.0], Vector[1.0,1.0]].mean => Vector[0.5,0.5]
|
180
|
+
def mean
|
181
|
+
return self.sum / self.size
|
182
|
+
end
|
183
|
+
|
184
|
+
# compute range of an array
|
185
|
+
# - if proc nil, returns (min..max)
|
186
|
+
# - else, first compute new array with proc, then (min..max) on this array
|
187
|
+
# [1.0, 3.0, 2.0].range => (1.0..3.0)
|
188
|
+
def range( proc=nil )
|
189
|
+
if not proc
|
190
|
+
return (self.min..self.max)
|
191
|
+
else
|
192
|
+
arraytmp = self.map {|item| item.send( proc )}
|
193
|
+
return arraytmp.range
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
# alias for sub(2)
|
198
|
+
# [1,2,3,4].half => [1,3]
|
199
|
+
def half( &block )
|
200
|
+
return sub(2,&block)
|
201
|
+
end
|
202
|
+
|
203
|
+
# flatten an array of arrays
|
204
|
+
# [[1,1], [2,2]].flattenonce => [1,1,2,2]
|
205
|
+
def flattenonce
|
206
|
+
result = []
|
207
|
+
self.each do |subarray|
|
208
|
+
result += subarray
|
209
|
+
end
|
210
|
+
return result
|
211
|
+
end
|
212
|
+
|
213
|
+
# same as Enumerator.each_slice with implicit size given by block.arity, or explicit if no blocks
|
214
|
+
# (in that case, return array of array)
|
215
|
+
# same enumeration model as for Tcl foreach command (see Array.zip method for further compatibility)
|
216
|
+
# [1,2,3,4].foreach {|v1,v2| puts "#{v1} #{v2}"} => "1 2" "3 4"
|
217
|
+
def foreach( arity=nil, &block )
|
218
|
+
if not arity
|
219
|
+
arity = block.arity
|
220
|
+
end
|
221
|
+
if block
|
222
|
+
if arity == 1
|
223
|
+
return self.each( &block )
|
224
|
+
else
|
225
|
+
return self.each_slice(arity, &block)
|
226
|
+
end
|
227
|
+
else
|
228
|
+
return self.enum_slice(arity).to_a
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
# same as Enumerator.each_cons with implicit size given by block.arity, or explicit if no blocks
|
233
|
+
# (in that case, return array of array)
|
234
|
+
# [1,2,3,4].uplets {|v1,v2| puts "#{v1} #{v2}"} => "1 2" "2 3" "3 4"
|
235
|
+
def uplets(arity=nil, &block )
|
236
|
+
if not arity
|
237
|
+
arity = block.arity
|
238
|
+
end
|
239
|
+
if block
|
240
|
+
return self.each_cons(arity, &block)
|
241
|
+
else
|
242
|
+
return self.enum_cons(arity).to_a
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
# alias for uplets(2, &block)
|
247
|
+
# [1,2,3,4].pairs {|v| puts "#{v[0]} #{v[1]}"} => "1 2" "2 3" "3 4"
|
248
|
+
def pairs( &block )
|
249
|
+
return self.uplets(2, &block)
|
250
|
+
end
|
251
|
+
|
252
|
+
# alias for uplets(3, &block)
|
253
|
+
# [1,2,3,4].pairs {|v| puts "#{v[0]} #{v[1]} #{v[2]}"} => "1 2 3" "2 3 4"
|
254
|
+
def triplets( &block )
|
255
|
+
return self.uplets(3, &block)
|
256
|
+
end
|
257
|
+
|
258
|
+
# aarity = array of arity
|
259
|
+
# if nil, default value is Array.new( self.size, 1 )
|
260
|
+
# size of aarity must be inferior or equal to self.size. If inferior, is completed with 1
|
261
|
+
# Rke : with array size 1, is equivalent to foreach
|
262
|
+
# [ [1,2,3,4], [a,b] ].forzip( [2,1] ) => [1,2,a,3,4,b]
|
263
|
+
# [ [1,2,3,4], [a,b] ].forzip => [[1,a], [2,b], [3,nil], [4,nil]]
|
264
|
+
# [ [a,b], [1,2,3,4] ].forzip => [[a,1], [b,2], [nil,3], [nil,4]]
|
265
|
+
def forzip(aarity=nil, &block)
|
266
|
+
if not aarity
|
267
|
+
aarity = Array.new( self.size, 1 )
|
268
|
+
end
|
269
|
+
if aarity.size < self.size
|
270
|
+
aarity = aarity.concat( Array.new( self.size - aarity.size, 1 ) )
|
271
|
+
end
|
272
|
+
tozip = Array.new
|
273
|
+
self.zip( aarity ) do |subarray, arity|
|
274
|
+
tozip.push( subarray.foreach(arity) )
|
275
|
+
end
|
276
|
+
result = tozip[0].zip( *tozip[1..-1] )
|
277
|
+
result = result.flattenonce.flattenonce
|
278
|
+
if block
|
279
|
+
return result.foreach( nil, &block )
|
280
|
+
end
|
281
|
+
return result
|
282
|
+
end
|
283
|
+
|
284
|
+
# in same idea as forzip, but with explicit array index
|
285
|
+
# if pattern is nil, is equivalent to [0,1,..., self.size-1]
|
286
|
+
# [ [1,2,3,4], [a,b] ].forpattern( [0,0,1] ) => [1,2,a,3,4,b]
|
287
|
+
# [ [1,2,3,4], [a,b] ].forpattern( [0,1,0] ) => [1,a,2,3,b,4]
|
288
|
+
#
|
289
|
+
# Rke : an interesting application is to use this method to filter some item periodically
|
290
|
+
# for example [[array]].forpattern( [0,0] ) {|i,j| result.push( i )} take only first item on a pair (to be tested)
|
291
|
+
# Rke2 : not so usefull for the moment (since compared with forzip, the only added value is to allow permutations of values between different subarrays)
|
292
|
+
def forpattern(pattern, &block)
|
293
|
+
cindexes = Array.new( self.size, 0 )
|
294
|
+
result = []
|
295
|
+
while true
|
296
|
+
newitem = []
|
297
|
+
pattern.each do |arrayindex|
|
298
|
+
newitem.push( self.[]( arrayindex )[ cindexes[ arrayindex] ] )
|
299
|
+
cindexes[ arrayindex] += 1
|
300
|
+
end
|
301
|
+
if newitem.compact.size == 0
|
302
|
+
break
|
303
|
+
end
|
304
|
+
result += newitem
|
305
|
+
end
|
306
|
+
# result = result.flatten
|
307
|
+
if block
|
308
|
+
return result.foreach( nil, &block )
|
309
|
+
end
|
310
|
+
return result
|
311
|
+
end
|
312
|
+
|
313
|
+
# -------------------------------------------------------------
|
314
|
+
# Samplable interface include and overriding
|
315
|
+
# -------------------------------------------------------------
|
316
|
+
include Samplable
|
317
|
+
include Splittable
|
318
|
+
|
319
|
+
# FloatFunctor overloading to synchronize content sampling and splitting
|
320
|
+
def compute( inputs, type )
|
321
|
+
return self.map {|v| v.compute( inputs, type )}.forzip
|
322
|
+
end
|
323
|
+
|
324
|
+
end
|
325
|
+
|
326
|
+
# -------------------------------------------------------------
|
327
|
+
# String class
|
328
|
+
# -------------------------------------------------------------
|
329
|
+
|
330
|
+
class String #:nodoc:
|
331
|
+
|
332
|
+
def subreplace (tokens)
|
333
|
+
gsub(/#{tokens.keys.join("|")}/) { tokens[$&] }
|
334
|
+
end
|
335
|
+
|
336
|
+
end
|
337
|
+
|
338
|
+
class Float #:nodoc:
|
339
|
+
|
340
|
+
def complement( max = 1.0, min = 0.0 )
|
341
|
+
return ( max - ( self.to_f - min ) )
|
342
|
+
end
|
343
|
+
|
344
|
+
def randsplit(minsize=0.0)
|
345
|
+
v = self.to_f
|
346
|
+
rand = minsize + Kernel::rand * (1.0 - minsize )
|
347
|
+
min = v * rand
|
348
|
+
max = v - min
|
349
|
+
return [min, max]
|
350
|
+
end
|
351
|
+
|
352
|
+
end
|
353
|
+
|
354
|
+
|
355
|
+
class Integer #:nodoc:
|
356
|
+
|
357
|
+
|
358
|
+
def randsplit!(minsize=0.0)
|
359
|
+
size = 1.0
|
360
|
+
nsplit = self.to_i
|
361
|
+
rsize = size - nsplit * minsize
|
362
|
+
if rsize < 0.0
|
363
|
+
return []
|
364
|
+
end
|
365
|
+
|
366
|
+
minsizes = Array.new( nsplit, minsize )
|
367
|
+
# puts "minsizes #{minsizes.join(" ")}"
|
368
|
+
|
369
|
+
randarray = [0.0]
|
370
|
+
subarray = (0.0..rsize).rand( nsplit - 1 )
|
371
|
+
Trace("subarray #{subarray.inspect}")
|
372
|
+
randarray += subarray
|
373
|
+
randarray.push( rsize )
|
374
|
+
randarray.sort!
|
375
|
+
|
376
|
+
# puts "randarray #{randarray.join(" ")}"
|
377
|
+
|
378
|
+
rsizes = Array.new
|
379
|
+
randarray.each_cons(2) { |min, max| rsizes.push( max - min ) }
|
380
|
+
|
381
|
+
# puts "rsizes #{rsizes.join(" ")}"
|
382
|
+
|
383
|
+
result = Array.new
|
384
|
+
minsizes.zip( rsizes ) {|minsize, rsize| result.push( minsize + rsize )}
|
385
|
+
|
386
|
+
# puts "result randsplit! #{result.join(" ")}"
|
387
|
+
|
388
|
+
return result
|
389
|
+
end
|
390
|
+
|
391
|
+
def randsplitsum!(minsize=0.0)
|
392
|
+
preresult = self.randsplit!(minsize)
|
393
|
+
|
394
|
+
result = Array.new
|
395
|
+
sum = 0
|
396
|
+
preresult.each {|v| sum += v; result.push( sum ) }
|
397
|
+
|
398
|
+
# puts "result randsplitsum! #{result.join(" ")}"
|
399
|
+
return result
|
400
|
+
end
|
401
|
+
|
402
|
+
|
403
|
+
end
|
404
|
+
|
data/lib/xrvg.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
# This file is to be included if you want to start a XRVG script
|
2
|
+
#
|
3
|
+
# Please refer to README for XRVG introduction
|
4
|
+
|
5
|
+
# XRVG version (used in rakefile)
|
6
|
+
XRVG_VERSION = "0.0.1"
|
7
|
+
|
8
|
+
# Standard Ruby extensions
|
9
|
+
require 'enumerator'
|
10
|
+
|
11
|
+
# XRVG Infrastructure
|
12
|
+
require 'trace'
|
13
|
+
require 'assertion'
|
14
|
+
|
15
|
+
# XRVG new mixins
|
16
|
+
require 'samplation'
|
17
|
+
require 'attributable'
|
18
|
+
require 'interpolation'
|
19
|
+
|
20
|
+
# XRVG base class extensions
|
21
|
+
require 'utils'
|
22
|
+
require 'geometry2D'
|
23
|
+
|
24
|
+
# XRVG base classes
|
25
|
+
require 'color'
|
26
|
+
require 'frame'
|
27
|
+
require 'shape'
|
28
|
+
require 'render'
|
29
|
+
# require 'bezier'
|
30
|
+
# require 'bezierspline'
|
31
|
+
|
32
|
+
# XRVG extensions
|
33
|
+
# require 'bezierbuilders'
|
34
|
+
# require 'beziertools'
|
35
|
+
# require 'interbezier'
|
36
|
+
# require 'ondulation'
|
37
|
+
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'attributable'
|
3
|
+
require 'utils'
|
4
|
+
|
5
|
+
class AttrClass
|
6
|
+
include Attributable
|
7
|
+
|
8
|
+
attribute :a, 1.0
|
9
|
+
attribute :b, nil, Float
|
10
|
+
attribute :c
|
11
|
+
end
|
12
|
+
|
13
|
+
|
14
|
+
# Test class
|
15
|
+
class AttributableTest < Test::Unit::TestCase
|
16
|
+
|
17
|
+
def test_nominal
|
18
|
+
obj = AttrClass[ :b, 2.0, :c, 3.0 ]
|
19
|
+
assert_equal( 1.0, obj.a)
|
20
|
+
assert_equal( 2.0, obj.b)
|
21
|
+
assert_equal( 3.0, obj.c)
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
data/test/test_color.rb
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'color'
|
3
|
+
|
4
|
+
|
5
|
+
class ColorTest < Test::Unit::TestCase
|
6
|
+
|
7
|
+
def test_color
|
8
|
+
color = Color[0.1, 0.2, 0.3, 0.4]
|
9
|
+
assert_equal( 0.1, color.r )
|
10
|
+
assert_equal( 0.2, color.g )
|
11
|
+
assert_equal( 0.3, color.b )
|
12
|
+
assert_equal( 0.4, color.a )
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_colors
|
16
|
+
black = Color[0.0, 0.0, 0.0, 1.0]
|
17
|
+
white = Color[1.0, 1.0, 1.0, 1.0]
|
18
|
+
assert_equal( black, Color.black )
|
19
|
+
assert_equal( white, Color.white )
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_svg
|
23
|
+
assert_equal( "rgb(0,0,0)", Color.black.svg )
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_hsv
|
27
|
+
black = Color[0.0, 0.0, 0.0, 1.0]
|
28
|
+
white = Color[1.0, 1.0, 1.0, 1.0]
|
29
|
+
red = Color[1.0, 0.0, 0.0, 1.0]
|
30
|
+
assert_equal( black, Color.hsv( 0.0, 0.0, 0.0, 1.0 ) )
|
31
|
+
assert_equal( white, Color.hsv( 0.0, 0.0, 1.0, 1.0 ) )
|
32
|
+
assert_equal( red, Color.hsv( 0.0, 1.0, 1.0, 1.0 ) )
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
class PaletteTest < Test::Unit::TestCase
|
39
|
+
|
40
|
+
def test_palette
|
41
|
+
palette = Palette.new( :colorlist, [ Color.black, 0.0, Color.white, 1.0 ] )
|
42
|
+
assert_equal( Color[0.5, 0.5, 0.5, 1.0], palette.color( 0.5 ) )
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
class GradientTest < Test::Unit::TestCase
|
47
|
+
|
48
|
+
def test_gradient
|
49
|
+
gradient = LinearGradient.new( :colorlist, [Color.black, 0.0, Color.white, 1.0] )
|
50
|
+
assert_equal( gradient.svgdef,
|
51
|
+
"<linearGradient id=\"%ID%\" x1=\"0%\" y1=\"0%\" x2=\"0%\" y2=\"100%\">\n<stop offset=\"0.0\" stop-color=\"rgb(0,0,0)\" stop-opacity=\"1.0\"/>\n<stop offset=\"1.0\" stop-color=\"rgb(255,255,255)\" stop-opacity=\"1.0\"/>\n</linearGradient>")
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
if nil
|
56
|
+
def test_gradient1
|
57
|
+
require 'render'
|
58
|
+
require 'shape'
|
59
|
+
render = SVGRender.new( :filename, "gradient1.svg" )
|
60
|
+
render.add( Circle.new, Style.new( :stroke, "none", :fill, LinearGradient.new( :colorlist, [Color.black, 0.0, Color.white, 1.0] ) ) )
|
61
|
+
render.end
|
62
|
+
assert( File.exist?( "gradient1.png" ) )
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
if nil
|
67
|
+
def test_gradient2
|
68
|
+
require 'render'
|
69
|
+
require 'shape'
|
70
|
+
render = SVGRender.new( :filename, "gradient2.svg" )
|
71
|
+
circle = Circle.new
|
72
|
+
style = Style.new( :stroke, "none", :fill, CircularGradient.new( :colorlist, [Color.black(1.0), 0.0, Color.black(0.0), 1.0], :circle, circle ) )
|
73
|
+
render.add( circle, style )
|
74
|
+
render.end
|
75
|
+
assert( File.exist?( "gradient2.png" ) )
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
data/test/test_frame.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'frame'
|
3
|
+
require 'geometry2D'
|
4
|
+
|
5
|
+
class FrameTest < Test::Unit::TestCase
|
6
|
+
|
7
|
+
def test_frame1
|
8
|
+
frame = Frame[ :center, Vector[0.0,0.0], :vector, Vector[1.0,0.0], :rotation, 0.0, :scale, 1.0 ]
|
9
|
+
assert_equal( 0.0, frame.center[0] )
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'geometry2D.rb'
|
3
|
+
|
4
|
+
# Test class
|
5
|
+
class VectorTest < Test::Unit::TestCase
|
6
|
+
|
7
|
+
def test_indice
|
8
|
+
s = Vector[0,1]
|
9
|
+
assert_equal(1, s[1])
|
10
|
+
assert_equal(0, s[0])
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_add
|
14
|
+
s = Vector[0,1]
|
15
|
+
t = Vector[2,3]
|
16
|
+
assert_equal(Vector[2,4], s + t)
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_norm
|
20
|
+
assert_equal(Vector[0,1], Vector[0,2].norm)
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_angle
|
24
|
+
assert_equal(0.0, Vector[0,0].angle)
|
25
|
+
assert_equal(0.0, Vector[1,0].angle)
|
26
|
+
assert_equal(Math::PI * 0.5, Vector[0,1].angle)
|
27
|
+
assert_equal(-Math::PI * 0.5, Vector[0,-1].angle)
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_mean
|
31
|
+
assert_equal(Vector[0,1], (Vector[0,0]..Vector[0,2]).middle)
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_length
|
35
|
+
assert_equal(1,Vector[0,1].length)
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_interpol
|
39
|
+
assert_equal(Vector[0.2,1.4], (Vector[0.0, 1.0]..Vector[1.0, 3.0]).sample( 0.2 ))
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_createwithpoints
|
43
|
+
|
44
|
+
assert_equal(Vector[1,1], Point[1,1] - Point[0,0])
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_ortho
|
49
|
+
assert_equal(Vector[-0.6,0.5],
|
50
|
+
Vector[0.5,0.6].ortho)
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_reverse
|
54
|
+
assert_equal(Vector[-0.6,-0.5],
|
55
|
+
Vector[0.6,0.5].reverse)
|
56
|
+
end
|
57
|
+
|
58
|
+
def test_viewbox
|
59
|
+
assert_equal( [1.0, 1.0, 2.0, 2.0],
|
60
|
+
Point.viewbox( [Point[1.0, 2.0], Point[2.0, 1.0]] ))
|
61
|
+
end
|
62
|
+
|
63
|
+
def test_size
|
64
|
+
assert_equal( [1.0, 1.0],
|
65
|
+
Point.size( [Point[1.0, 2.0], Point[2.0, 1.0]] ))
|
66
|
+
end
|
67
|
+
|
68
|
+
def test_operation_sequences
|
69
|
+
assert_equal(Vector[0.0,1.0],
|
70
|
+
Vector[1.0,0.0].norm.ortho)
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_inner_product
|
74
|
+
assert_equal( 1.0, Vector[1.0, 0.0].inner_product( Vector[1.0,1.0] ) )
|
75
|
+
end
|
76
|
+
end
|
data/test/test_render.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'render'
|
3
|
+
|
4
|
+
class SVGRenderTest < Test::Unit::TestCase
|
5
|
+
|
6
|
+
|
7
|
+
|
8
|
+
def test_raster
|
9
|
+
if nil
|
10
|
+
require 'shape'
|
11
|
+
render = SVGRender.new( :filename, "output/svgrender.svg" )
|
12
|
+
render.add( Circle[] )
|
13
|
+
render.end
|
14
|
+
assert( File.exist?( "svgrender.jpg" ) )
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
data/test/test_style.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'style'
|
3
|
+
|
4
|
+
class StyleTest < Test::Unit::TestCase
|
5
|
+
|
6
|
+
def test_svgline
|
7
|
+
style = Style.new(:fill, "red", :stroke, "none")
|
8
|
+
assert_equal( 'style="opacity:1.0;fill:red;fill-opacity:1.0;stroke:none;stroke-width:1.0;stroke-opacity:1.0"', style.svgline )
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_default
|
12
|
+
style = Style.new
|
13
|
+
assert_equal( 'style="opacity:1.0;fill:none;fill-opacity:1.0;stroke:none;stroke-width:1.0;stroke-opacity:1.0"', style.svgline )
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|