xrvg 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|