xrvg 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. data/CHANGES +8 -0
  2. data/README +1 -1
  3. data/Rakefile +36 -6
  4. data/examples/arciterate1.rb +13 -0
  5. data/examples/arcrecurse1.rb +30 -0
  6. data/examples/arcrecurse2.rb +37 -0
  7. data/examples/circleiterate1.rb +9 -0
  8. data/examples/circleiterate2.rb +11 -0
  9. data/examples/circleiterate3.rb +13 -0
  10. data/examples/circlerecurse1.rb +27 -0
  11. data/examples/circlerecurse2.rb +27 -0
  12. data/examples/circlerecurseall.rb +29 -0
  13. data/examples/euclideangeo.rb +11 -0
  14. data/examples/evolution1.rb +8 -0
  15. data/examples/evolution2.rb +9 -0
  16. data/examples/evolution3.rb +10 -0
  17. data/examples/fuseaugeo.rb +16 -0
  18. data/examples/gradientgeo.rb +21 -0
  19. data/examples/interbeziergeo1.rb +14 -0
  20. data/examples/interbeziergeo2.rb +17 -0
  21. data/examples/interbeziergeo3.rb +17 -0
  22. data/examples/offsetgeo.rb +16 -0
  23. data/lib/bezier.rb +37 -3
  24. data/lib/bezierbuilders.rb +17 -1
  25. data/lib/beziermotifs.rb +11 -4
  26. data/lib/bezierspline.rb +23 -1
  27. data/lib/beziertools.rb +48 -14
  28. data/lib/color.rb +55 -8
  29. data/lib/fitting.rb +2 -2
  30. data/lib/geometry2D.rb +10 -3
  31. data/lib/geovariety.rb +128 -0
  32. data/lib/interbezier.rb +4 -4
  33. data/lib/interpolation.rb +30 -17
  34. data/lib/parametriclength.rb +3 -2
  35. data/lib/render.rb +1 -2
  36. data/lib/samplation.rb +121 -19
  37. data/lib/shape.rb +2 -2
  38. data/lib/spiral.rb +72 -0
  39. data/lib/utils.rb +97 -76
  40. data/lib/xrvg.rb +3 -3
  41. data/test/test_bezier.rb +17 -2
  42. data/test/test_bezierbuilders.rb +1 -1
  43. data/test/test_beziertools.rb +7 -0
  44. data/test/test_color.rb +12 -0
  45. data/test/test_geovariety.rb +105 -0
  46. data/test/test_interpolation.rb +2 -1
  47. data/test/test_render.rb +0 -4
  48. data/test/test_sample.rb +28 -0
  49. data/test/test_spiral.rb +22 -0
  50. data/test/test_utils.rb +65 -40
  51. metadata +26 -2
data/lib/samplation.rb CHANGED
@@ -3,6 +3,8 @@
3
3
  # The base module is FloatFunctor, used by Samplable and Splittable
4
4
  #
5
5
 
6
+ require 'attributable'
7
+
6
8
  module XRVG
7
9
  #
8
10
  # Base module to define float lists processing and computation.
@@ -25,7 +27,7 @@ module FloatFunctor
25
27
 
26
28
  # building recursivity method
27
29
  #
28
- # is private ?
30
+ # is private => no for Array
29
31
  def addfilter( newfilter )
30
32
  if not @subfilter
31
33
  @subfilter = newfilter
@@ -123,9 +125,20 @@ module FloatFunctor
123
125
  return self.addfilter( Filter.with {|x| 1.0 - Math.exp(-speed * x)} )
124
126
  end
125
127
 
128
+ # geometric filter full
129
+ def geofull( factor )
130
+ return self.addfilter( GeoFullFilter.new( factor ) )
131
+ end
132
+
133
+
134
+ # sin filter
135
+ def sin( speed=1.0, phase=0.0 )
136
+ return self.addfilter( Filter.with {|x| Math.sin( speed * x * Math::PI + phase) } )
137
+ end
138
+
126
139
  # random filter
127
- def random()
128
- return self.addfilter( RandomFilter.new )
140
+ def random(*args)
141
+ return self.addfilter( RandomFilter.new(*args) )
129
142
  end
130
143
 
131
144
  # sorting filter
@@ -133,6 +146,12 @@ module FloatFunctor
133
146
  return self.addfilter( SortFilter.new )
134
147
  end
135
148
 
149
+ # shuffle filter
150
+ def shuffle()
151
+ return self.addfilter( ShuffleFilter.new )
152
+ end
153
+
154
+
136
155
  # alternate filter
137
156
  def alternate()
138
157
  return self.addfilter( AlternateFilter.new )
@@ -190,14 +209,6 @@ module Samplable
190
209
  # alias for mean
191
210
  alias middle mean
192
211
 
193
- # alias for .random.samples
194
- def rand(nsamples=1,&block)
195
- inputs = []
196
- nsamples.times {|v| inputs.push( Kernel::rand )}
197
- result = self.process( inputs, :sample, &block )
198
- return nsamples == 1 ? result[0] : result
199
- end
200
-
201
212
  # to be overloaded if needed
202
213
  #
203
214
  # called by FloatFunctor apply method
@@ -297,7 +308,6 @@ end
297
308
  # this allow to do for example
298
309
  # [bezier1.filter(:point), bezier1.filter(:tangent), palette].samples( 10 ) do |point, tangent, color|
299
310
  class Filter
300
-
301
311
  include Samplable
302
312
 
303
313
  # to define a filter on "object" with method "samplemethod", or with a block (exclusive)
@@ -329,26 +339,85 @@ class Filter
329
339
  end
330
340
 
331
341
 
332
- # RandomFilter class, to resample randomly
342
+ # = RandomFilter class, to resample randomly
343
+ # == Attributes
344
+ # attribute :mindiff, 0.0
345
+ # attribute :sort, false
346
+ # :mindiff specifies which minimum interval must be preserved between random values. Of course, the number of sampling must then be above a given value so that this constraint can be verified.
333
347
  class RandomFilter < Filter
334
- def initialize(*args) #:nodoc:
348
+ include Attributable
349
+ attribute :mindiff, 0.0
350
+ attribute :sort, false
351
+
352
+ # make sampling by trying to check :mindiff constraint
353
+ #
354
+ # generate an exception if not possible
355
+ def rawtransforms(nsamples)
356
+ size = 1.0
357
+ nsplit = nsamples - 1
358
+ rsize = size - nsplit * @mindiff
359
+ if rsize < 0.0
360
+ raise("RandomFilter rawtransforms error: nsamples #{nsamples} mindiff #{@mindiff} are incompatible")
361
+ end
362
+
363
+ mindiffs = Array.new( nsplit, @mindiff )
364
+
365
+ # compute now nsplit values whose sum is <= to rsize
366
+ randarray = [0.0]
367
+ subarray = (0.0..rsize).rand( nsplit-1 )
368
+ if not subarray.is_a? Array
369
+ subarray = [subarray]
370
+ end
371
+ randarray += subarray
372
+ randarray.push( rsize )
373
+ randarray.sort!
374
+
375
+ rsizes = Array.new
376
+ randarray.each_cons(2) { |min, max| rsizes.push( (0.0..max-min).rand ) }
377
+
378
+ rsum = rsizes.sum
379
+ root = (0.0..(rsize-rsum)).rand
380
+
381
+ Trace("mindiffs #{mindiffs.inspect} rsizes #{rsizes.inspect} rsize #{rsize} rsum #{rsum} root #{root}")
382
+
383
+ preresult = []
384
+ mindiffs.zip( rsizes ) {|mindiff, rsize| preresult.push( mindiff + rsize )}
385
+
386
+ result = [root]
387
+ preresult.each {|v| newv = result[-1] + v; result << newv }
388
+
389
+ return result
335
390
  end
336
391
 
337
- def transform(abs) #:nodoc:
392
+ # do (0.0..1.0).rand to speed up computation if @mindiff is 0.0
393
+ def basictransform( v )
338
394
  return (0.0..1.0).rand
339
395
  end
340
396
 
341
397
  def transforms( inputs, type ) #:nodoc:
342
- result = inputs.map { |v| self.transform( v ) }
343
398
  if type == :split
344
- result[0] = 0.0
345
- result[-1] = 1.0
399
+ @sort = true
400
+ end
401
+ if @mindiff == 0.0
402
+ result = inputs.map { |v| self.basictransform( v ) }
403
+ if @sort
404
+ result = result.sort
405
+ end
406
+ if type == :split
407
+ result[0] = 0.0
408
+ result[-1] = 1.0
409
+ end
410
+ else
411
+ result = self.rawtransforms( inputs.size )
412
+ if not @sort
413
+ result = result.shuffle
414
+ end
346
415
  end
347
416
  return result
348
417
  end
349
418
  end
350
419
 
351
- # SortFilter, to sort inputs (in particular from Random)
420
+ # SortFilter, to sort inputs (in particular from Shuffle)
352
421
  class SortFilter < Filter
353
422
  def initialize(*args) #:nodoc:
354
423
  end
@@ -356,9 +425,42 @@ class SortFilter < Filter
356
425
  def transforms( inputs, type ) #:nodoc:
357
426
  return inputs.sort
358
427
  end
428
+ end
429
+
430
+ # GeoFullFilter, to transform inputs into geometrical sequence converging to 1.0
431
+ class GeoFullFilter < Filter
432
+ def initialize(factor) #:nodoc:
433
+ @factor = factor
434
+ end
359
435
 
436
+
437
+ # make sampling by trying to check :mindiff constraint
438
+ #
439
+ # generate an exception if not possible
440
+ def transforms( inputs, type ) #:nodoc:
441
+ nsamples = inputs.size
442
+ result = [1.0]
443
+ (nsamples-1).times do
444
+ result << result[-1] / @factor
445
+ end
446
+ range = (1.0..result[-1])
447
+ result = result.map {|v| range.abscissa( v )}
448
+ return result
449
+ end
450
+ end
451
+
452
+
453
+ # ShuffleFilter, to unsort inputs (in particular from Random)
454
+ class ShuffleFilter < Filter
455
+ def initialize(*args) #:nodoc:
456
+ end
457
+
458
+ def transforms( inputs, type ) #:nodoc:
459
+ return inputs.sort_by { rand }
460
+ end
360
461
  end
361
462
 
463
+
362
464
  # AlternateFilter, to inverse one value per two
363
465
  class AlternateFilter < Filter
364
466
  def initialize(range=nil) #:nodoc:
data/lib/shape.rb CHANGED
@@ -4,10 +4,10 @@
4
4
  # - Curve interface
5
5
  # - Line class
6
6
  # - Circle class
7
+ require 'utils'
7
8
  require 'frame'
8
9
  require 'geometry2D'
9
- require 'utils'
10
- require 'attributable'
10
+
11
11
 
12
12
  module XRVG
13
13
  # Shape abstract interface
data/lib/spiral.rb ADDED
@@ -0,0 +1,72 @@
1
+ # File dedicated to Spiral curves
2
+ # - Spiral
3
+ # - SpiralParam
4
+ # - SpiralFrise
5
+
6
+ require 'shape'
7
+
8
+ module XRVG
9
+
10
+ # abstract class to define spiral types
11
+ #
12
+ # use compute_radius to compute nsamples reference points, before interpolating with SimpleBezier
13
+ class GSpiral < BezierBuilder
14
+ attribute :center, V2D::O, V2D
15
+ attribute :ext, V2D::O + V2D::X, V2D
16
+ attribute :curvature, 1.0
17
+ attribute :nsamples, 100
18
+
19
+ def compute_radius( r0, angle0, curvature, angle )
20
+ raise NotImplementedError.new("#{self.class.name}#compute_radius is an abstract method.")
21
+ end
22
+
23
+ def maxangle( r0, angle0, curvature )
24
+ raise NotImplementedError.new("#{self.class.name}#maxangle is an abstract method.")
25
+ end
26
+
27
+ def compute()
28
+ points = []
29
+ r0, angle0 = (@ext - @center).coords(:polar)
30
+ maxangle = self.maxangle( r0, angle0, @curvature )
31
+ [(r0..0.0), (angle0..maxangle)].samples( self.nsamples ) do |radius, angle|
32
+ r = self.compute_radius( r0, angle0, @curvature, angle )
33
+ point = V2D.polar( r, angle )
34
+ points.push( @center + point )
35
+ end
36
+ return SimpleBezier.build( :support, points ).data
37
+ end
38
+ end
39
+
40
+ # at angle angle0, r = r0
41
+ # at angle angle0 + curvature, r = 0.0
42
+ class SpiralLinear < GSpiral
43
+
44
+ def maxangle( r0, angle0, curvature )
45
+ return (angle0 + curvature)
46
+ end
47
+
48
+ def compute_radius( r0, angle0, curvature, angle )
49
+ return r0 * (1.0 - ( 1.0 + (Math.exp( - 10.0 * ( angle- angle0) / curvature ) ) ) * ( angle - angle0 ) /curvature )
50
+ # return r0 * (1.0 - ( angle - angle0 ) /curvature )
51
+ end
52
+
53
+ end
54
+
55
+ # curvature is in number of tour before center % extremity
56
+ class SpiralLog < GSpiral
57
+
58
+ def nsamples
59
+ return (curvature * 15.0).to_i
60
+ end
61
+
62
+ def compute_radius( r0, angle0, curvature, angle )
63
+ return r0 * Math.exp( -(angle-angle0) / curvature )
64
+ end
65
+
66
+ def maxangle( r0, angle0, curvature )
67
+ return angle0 - curvature * Math.log( 0.001 )
68
+ end
69
+ end
70
+
71
+ end #XRVG
72
+
data/lib/utils.rb CHANGED
@@ -74,6 +74,39 @@ class Range
74
74
  return value
75
75
  end
76
76
 
77
+ # return modulo of value given interval
78
+ # (-1.0..1.5).modulo( 2.0 ) => -0.5
79
+ #
80
+ # TODO: manage special case range size = 0.0
81
+ def modulo( value )
82
+ return ((value - self.min)%self.size + self.min)
83
+ end
84
+
85
+ # compute list of "modulo boundaries"
86
+ # (-1.0..1.5).modulos( (-1.2..2.4) ) => [(1.3..1.5), (-1.0..1.5), (-1.0..0.4)]
87
+ def modulos( range )
88
+ t1 = self.modulo( range.min )
89
+ t2 = self.modulo( range.max )
90
+ s1 = ((range.min - self.min)/self.size).floor
91
+ s2 = ((range.max - self.min)/self.size).floor
92
+ if s1 == s2
93
+ result = [(t1..t2)]
94
+ else
95
+ result = [(t1..self.max)]
96
+ (s2-s1-1).times do
97
+ result << (self.min..self.max)
98
+ end
99
+ if t2 - self.min > 0.0
100
+ result << (self.min..t2)
101
+ end
102
+ end
103
+ if range.begin > range.end
104
+ result = result.reverse.map {|v| v.reverse}
105
+ end
106
+ # Trace("modulos range #{range.inspect} result #{result.inspect}")
107
+ return result
108
+ end
109
+
77
110
  # return max value of range
78
111
  def max
79
112
  return (self.begin > self.end) ? self.begin : self.end
@@ -84,6 +117,11 @@ class Range
84
117
  return (self.begin < self.end) ? self.begin : self.end
85
118
  end
86
119
 
120
+ # return size of the range
121
+ def size
122
+ return (self.max - self.min)
123
+ end
124
+
87
125
  # -------------------------------------------------------------
88
126
  # Samplable interface include and overriding
89
127
  # -------------------------------------------------------------
@@ -97,8 +135,10 @@ class Range
97
135
  return (self.begin + ( self.end - self.begin ) * value)
98
136
  end
99
137
 
100
- # to speed up samplation on ranges, as used everywhere
101
- def generate( nsamples ) #:nodoc:
138
+ # Very fundamental generator
139
+ #
140
+ # Generates a sequence of "nsamples" floats between 0.0 and 1.0 (included)
141
+ def Range.generate( nsamples )
102
142
  result = []
103
143
  if nsamples == 1
104
144
  result = [0.0]
@@ -107,21 +147,26 @@ class Range
107
147
  end
108
148
  return result
109
149
  end
150
+
151
+ # Simply redirect on Range.generate
152
+ def generate( nsamples ) #:nodoc:
153
+ return Range.generate( nsamples )
154
+ end
110
155
 
111
156
  # apply_sample is good by default
112
157
  # apply_split is good by default
113
158
 
114
- # size of the range
115
- # (0.0..2.0).size => 2.0
116
- def size
117
- return self.end - self.begin
118
- end
119
-
120
159
  # returns a reversed range
121
160
  # (1.0..2.0).reverse => (2.0..1.0)
122
161
  def reverse
123
162
  return Range.new( self.end, self.begin )
124
163
  end
164
+
165
+ # returns an increasing Range
166
+ # (2.0..1.0).sort => (1.0..2.0)
167
+ def sort
168
+ return (self.begin > self.end ? Range.new( self.end, self.begin ) : Range.new( self.begin, self.end ))
169
+ end
125
170
 
126
171
  # resize range by factor, with fixed point center of the range
127
172
  # (1.0..2.0).resize( 0.5 ) => (1.25..1.75)
@@ -207,6 +252,14 @@ class Range
207
252
  return self.samples( samples )
208
253
  end
209
254
 
255
+ # alias for .random.samples
256
+ def rand(nsamples=1,&block)
257
+ inputs = []
258
+ nsamples.times {|v| inputs.push( Kernel::rand )}
259
+ result = self.process( inputs, :sample, &block )
260
+ return nsamples == 1 ? result[0] : result
261
+ end
262
+
210
263
  # deprecated
211
264
  #
212
265
  # TODO : must add gauss parameters
@@ -262,10 +315,22 @@ class Array
262
315
  return self.sum / self.size
263
316
  end
264
317
 
318
+ # return a random item from array
319
+ def choice
320
+ return self[Kernel::rand(self.size)]
321
+ end
322
+
265
323
  # compute range of an array by returning (min..max)
266
324
  # [1.0, 3.0, 2.0].range => (1.0..3.0)
325
+ # if proc supplied, use it to return range of subvalues
326
+ # [V2D::O, V2D::X].range( :x ) => (0.0..1.0)
267
327
  def range( proc=nil )
268
- return (self.min..self.max)
328
+ if not proc
329
+ return (self.min..self.max)
330
+ else
331
+ arraytmp = self.map {|item| item.send( proc )}
332
+ return arraytmp.range
333
+ end
269
334
  end
270
335
 
271
336
  # alias for sub(2)
@@ -384,6 +449,11 @@ class Array
384
449
  return result
385
450
  end
386
451
 
452
+ # shuffle values in array
453
+ def shuffle
454
+ return self.sort_by{ rand }
455
+ end
456
+
387
457
  # -------------------------------------------------------------
388
458
  # Samplable interface include and overriding
389
459
  # -------------------------------------------------------------
@@ -395,6 +465,10 @@ class Array
395
465
  return self.map {|v| v.compute( inputs, type )}.forzip(nil,&block)
396
466
  end
397
467
 
468
+ def addfilter( newfilter )
469
+ self.each {|v| v.addfilter( newfilter )}
470
+ end
471
+
398
472
  end
399
473
 
400
474
  # -------------------------------------------------------------
@@ -409,24 +483,21 @@ class String #:nodoc:
409
483
 
410
484
  end
411
485
 
412
- class Float #:nodoc:
413
-
414
- def complement( max = 1.0, min = 0.0 )
415
- return ( max - ( self.to_f - min ) )
416
- end
417
-
486
+ # Ruby base class Float extension
487
+ #
488
+ # Mainly to be able to compare two floats with specific accuracy
489
+ class Float
490
+
491
+ # compare two Float with specific precision
492
+ # assert( 0.25.fequal?( 0.26,0.02) )
493
+ # assert_equal( false, 0.25.fequal?( 0.26,0.01) )
418
494
  def fequal?( other, epsilon=0.0000000001 )
419
495
  return ((self - other).abs < epsilon)
420
496
  end
421
497
 
422
- def randsplit(minsize=0.0)
423
- v = self.to_f
424
- rand = minsize + Kernel::rand * (1.0 - minsize )
425
- min = v * rand
426
- max = v - min
427
- return [min, max]
428
- end
429
-
498
+ # sort and remove duplicated elements of a float list with specific precision
499
+ # assert_equal( [0.25], Float.sort_float_list([0.26,0.25], 0.02 ) )
500
+ # assert_equal( [0.25,0.26], Float.sort_float_list([0.26,0.25], 0.01 ) )
430
501
  def Float.sort_float_list( floatlist, epsilon=0.0000001 )
431
502
  floatlist = floatlist.uniq.sort
432
503
  result = [floatlist[0]]
@@ -438,6 +509,9 @@ class Float #:nodoc:
438
509
  return result
439
510
  end
440
511
 
512
+ # check if an Float item is included in a Float list, with specific precision
513
+ # assert( Float.floatlist_include?( [1.0,2.0,3.0001,4.0], 3.0, 0.001 ) )
514
+ # assert_equal( false, Float.floatlist_include?( [1.0,2.0,3.0001,4.0], 3.0, 0.0001 ) )
441
515
  def Float.floatlist_include?( floatlist, float, epsilon=0.0000001 )
442
516
  floatlist.each do |item|
443
517
  if item.fequal?( float, epsilon )
@@ -446,58 +520,5 @@ class Float #:nodoc:
446
520
  end
447
521
  return false
448
522
  end
449
-
450
-
451
- end
452
-
453
-
454
- class Integer #:nodoc:
455
-
456
-
457
- def randsplit!(minsize=0.0)
458
- size = 1.0
459
- nsplit = self.to_i
460
- rsize = size - nsplit * minsize
461
- if rsize < 0.0
462
- return []
463
- end
464
-
465
- minsizes = Array.new( nsplit, minsize )
466
- # puts "minsizes #{minsizes.join(" ")}"
467
-
468
- randarray = [0.0]
469
- subarray = (0.0..rsize).rand( nsplit - 1 )
470
- Trace("subarray #{subarray.inspect}")
471
- randarray += subarray
472
- randarray.push( rsize )
473
- randarray.sort!
474
-
475
- # puts "randarray #{randarray.join(" ")}"
476
-
477
- rsizes = Array.new
478
- randarray.each_cons(2) { |min, max| rsizes.push( max - min ) }
479
-
480
- # puts "rsizes #{rsizes.join(" ")}"
481
-
482
- result = Array.new
483
- minsizes.zip( rsizes ) {|minsize, rsize| result.push( minsize + rsize )}
484
-
485
- # puts "result randsplit! #{result.join(" ")}"
486
-
487
- return result
488
- end
489
-
490
- def randsplitsum!(minsize=0.0)
491
- preresult = self.randsplit!(minsize)
492
-
493
- result = Array.new
494
- sum = 0
495
- preresult.each {|v| sum += v; result.push( sum ) }
496
-
497
- # puts "result randsplitsum! #{result.join(" ")}"
498
- return result
499
- end
500
-
501
-
502
523
  end
503
524
 
data/lib/xrvg.rb CHANGED
@@ -1,9 +1,9 @@
1
- # This file is to be included if you want to start a XRVG script
1
+ # This file has to be included if you want to start a XRVG script
2
2
  #
3
3
  # Please refer to README for XRVG introduction
4
4
 
5
5
  # XRVG version (used in rakefile)
6
- XRVG_VERSION = "0.0.5"
6
+ XRVG_VERSION = "0.0.6"
7
7
 
8
8
  # XRVG namespace
9
9
  module XRVG
@@ -39,7 +39,7 @@ require 'beziermotifs'
39
39
  require 'beziertools'
40
40
  require 'interbezier'
41
41
  require 'geovariety'
42
- # require 'spiral'
42
+ require 'spiral'
43
43
  # require 'graph'
44
44
 
45
45
 
data/test/test_bezier.rb CHANGED
@@ -147,6 +147,7 @@ class BezierTest < Test::Unit::TestCase
147
147
  [:raw, V2D[1.0, 0.0], V2D[2.0, 2.0], V2D[1.0, 1.0], V2D[2.0, 0.0] ],
148
148
  [:raw, V2D[2.0, 0.0], V2D[2.0, 2.0], V2D[1.0, 1.0], V2D[3.0, 0.0] ]]
149
149
  assert_equal( 3, Bezier.multi( pieces ).subbezier(0.1,0.9).piecenumber )
150
+ assert_equal( 3, Bezier.multi( pieces ).subbezier(0.9,0.1).piecenumber )
150
151
  end
151
152
 
152
153
  def test_computelength
@@ -237,7 +238,7 @@ class BezierTest < Test::Unit::TestCase
237
238
  end
238
239
 
239
240
  def test_gdebug
240
- require 'render'
241
+ # require 'render'
241
242
  render = SVGRender[]
242
243
  @@bezier.gdebug( render )
243
244
  end
@@ -256,7 +257,21 @@ class BezierTest < Test::Unit::TestCase
256
257
  assert( V2D.vequal?( V2D[0.5, 0.5], @@beziersym.filter(:point).sample( 0.5 ) ) )
257
258
  end
258
259
 
259
-
260
+ def test_transform
261
+ bezier = Bezier.raw( V2D[0.0, 0.0], V2D[1.0, 0.0], V2D[-1.0, 0.0], V2D[1.0, 0.0] )
262
+ # assert_equal( [V2D[0.0, 0.0], V2D[-1.0, 0.0], V2D[1.0, 0.0], V2D[-1.0, 0.0]], bezier.rotate( Range.Angle.sample( 0.5 ) ).pointlist )
263
+ assert_equal( V2D[0.0, 0.0], bezier.rotate( Range.Angle.sample( 0.5 ) ).firstpoint )
264
+ # assert_equal( bezier.pointlist, bezier.rotate( Range.Angle.sample( 1.0 ) ).pointlist )
265
+ assert_equal( bezier.firstpoint, bezier.rotate( Range.Angle.sample( 1.0 ) ).firstpoint )
266
+ # assert_equal( [V2D[0.0, 0.0], V2D[-1.0, 0.0], V2D[1.0, 0.0], V2D[-1.0, 0.0]], bezier.sym( V2D::O ).pointlist )
267
+ assert_equal( V2D[0.0, 0.0], bezier.sym( V2D::O ).firstpoint )
268
+ # assert_equal( bezier.pointlist, bezier.sym( V2D::O ).sym( V2D::O ).pointlist )
269
+ assert_equal( bezier.firstpoint, bezier.sym( V2D::O ).sym( V2D::O ).firstpoint )
270
+ # assert_equal( [V2D[0.0, 0.0], V2D[-1.0, 0.0], V2D[1.0, 0.0], V2D[-1.0, 0.0]], bezier.axesym( V2D::O, V2D[0.0,1.0] ).pointlist )
271
+ assert_equal( V2D[0.0, 0.0], bezier.axesym( V2D::O, V2D[0.0,1.0] ).firstpoint )
272
+ # assert_equal( bezier.pointlist, bezier.axesym( V2D::O, V2D[1.0,0.0] ).pointlist )
273
+ assert_equal( bezier.firstpoint, bezier.axesym( V2D::O, V2D[1.0,0.0] ).firstpoint )
274
+ end
260
275
  end
261
276
 
262
277
 
@@ -87,6 +87,6 @@ end
87
87
  class CircleTest < Test::Unit::TestCase
88
88
 
89
89
  def test_bezier
90
- assert_equal( 2, Circle[].bezier.piecenumber )
90
+ assert_equal( 4, Circle[].bezier.piecenumber )
91
91
  end
92
92
  end
@@ -9,6 +9,13 @@ class SimpleBezierTest < Test::Unit::TestCase
9
9
  assert_raise(RuntimeError){SimpleBezier[ :support, [V2D::O] ]}
10
10
  assert_equal( SimpleBezier[ :support, [V2D::O,V2D::X] ].point( 0.3 ), LinearBezier[ :support, [V2D::O,V2D::X] ].point( 0.3 ) )
11
11
  end
12
+
13
+ def test_interpolation
14
+ interpolator = Interpolator[ :samplelist, [0.0,0.0, 0.5,1.0, 1.0,0.0], :interpoltype, :simplebezier]
15
+ assert( 1.0.fequal?( interpolator.interpolate( 0.5 ) ) )
16
+ assert( 0.0.fequal?( interpolator.interpolate( 1.0 ) ) )
17
+ end
18
+
12
19
  end
13
20
 
14
21
  class ClosureTest < Test::Unit::TestCase
data/test/test_color.rb CHANGED
@@ -20,6 +20,7 @@ class ColorTest < Test::Unit::TestCase
20
20
  green = Color[0.0, 1.0, 0.0, 1.0]
21
21
  yellow = Color[1.0, 1.0, 0.0, 1.0]
22
22
  orange = Color[1.0, 0.5, 0.0, 1.0]
23
+ grey10 = Color[0.1, 0.1, 0.1, 1.0]
23
24
  assert_equal( black, Color.black )
24
25
  assert_equal( white, Color.white )
25
26
  assert_equal( red, Color.red )
@@ -27,6 +28,7 @@ class ColorTest < Test::Unit::TestCase
27
28
  assert_equal( green, Color.green )
28
29
  assert_equal( yellow, Color.yellow )
29
30
  assert_equal( orange, Color.orange )
31
+ assert_equal( grey10, Color.grey( 0.1 ) )
30
32
  end
31
33
 
32
34
  def test_rand
@@ -84,6 +86,10 @@ class ColorTest < Test::Unit::TestCase
84
86
  assert_equal( [25,25,25,25], Color[0.1,0.1,0.1,0.1].format255 )
85
87
  end
86
88
 
89
+ def test_operators
90
+ assert_equal( Color[0.2, 0.4, 0.6, 1.0], Color[0.1, 0.2, 0.3, 0.5 ] + Color[0.1, 0.2, 0.3, 0.5 ] )
91
+ assert_equal( Color[0.2, 0.4, 0.6, 1.0], Color[0.1, 0.2, 0.3, 0.5 ] * 2.0 )
92
+ end
87
93
  end
88
94
 
89
95
 
@@ -101,6 +107,12 @@ class PaletteTest < Test::Unit::TestCase
101
107
  palette = Palette.new( :colorlist, [ 0.0, Color.black, 0.3, Color.red, 1.0, Color.white ] ).reverse
102
108
  assert_equal( Color.red, palette.color( 0.7 ) )
103
109
  end
110
+
111
+ def test_interpolator
112
+ palette = Palette.new( :colorlist, [ 0.0, Color.black, 0.3, Color.red, 1.0, Color.white ] )
113
+ palette.interpoltype = :linear
114
+ assert_equal( :linear, palette.interpoltype )
115
+ end
104
116
 
105
117
  end
106
118