xrvg 0.0.3 → 0.0.4

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.
Files changed (59) hide show
  1. data/CHANGES +21 -0
  2. data/README +3 -3
  3. data/Rakefile +4 -4
  4. data/examples/bezierbasic.rb +1 -0
  5. data/examples/bezierbasicvector.rb +1 -0
  6. data/examples/foreach.rb +1 -0
  7. data/examples/geodash.rb +1 -0
  8. data/examples/geodash2.rb +1 -0
  9. data/examples/hellocrown.rb +1 -0
  10. data/examples/hellocrown2.rb +1 -0
  11. data/examples/hellocrownrecurse.rb +1 -0
  12. data/examples/helloworldcompact.rb +1 -0
  13. data/examples/helloworldexpanded.rb +1 -0
  14. data/examples/multibezierbasic.rb +1 -0
  15. data/examples/palette_circle.rb +1 -0
  16. data/examples/randomdash.rb +1 -0
  17. data/examples/range_examples.rb +1 -0
  18. data/examples/range_examples2.rb +1 -0
  19. data/examples/sample.rb +1 -0
  20. data/examples/simpledash.rb +1 -0
  21. data/examples/uplets.rb +1 -0
  22. data/lib/bezier.rb +21 -55
  23. data/lib/bezierbuilders.rb +194 -0
  24. data/lib/beziermotifs.rb +114 -0
  25. data/lib/bezierspline.rb +20 -75
  26. data/lib/beziertools.rb +211 -0
  27. data/lib/color.rb +26 -7
  28. data/lib/fitting.rb +203 -0
  29. data/lib/frame.rb +2 -1
  30. data/lib/geometry2D.rb +6 -5
  31. data/lib/interbezier.rb +87 -0
  32. data/lib/interpolation.rb +6 -5
  33. data/lib/parametriclength.rb +87 -0
  34. data/lib/render.rb +4 -9
  35. data/lib/samplation.rb +71 -82
  36. data/lib/shape.rb +47 -25
  37. data/lib/style.rb +2 -1
  38. data/lib/trace.rb +2 -0
  39. data/lib/utils.rb +111 -17
  40. data/lib/xrvg.rb +16 -6
  41. data/test/test_attributable.rb +34 -2
  42. data/test/test_bezier.rb +93 -2
  43. data/test/test_bezierbuilders.rb +92 -0
  44. data/test/test_beziertools.rb +97 -0
  45. data/test/test_color.rb +65 -24
  46. data/test/test_fitting.rb +47 -0
  47. data/test/test_frame.rb +7 -2
  48. data/test/test_geometry2D.rb +26 -7
  49. data/test/test_interbezier.rb +29 -0
  50. data/test/test_interpolation.rb +16 -1
  51. data/test/test_parametric_length.rb +15 -0
  52. data/test/test_render.rb +54 -6
  53. data/test/test_shape.rb +103 -10
  54. data/test/test_trace.rb +13 -0
  55. data/test/test_utils.rb +114 -12
  56. data/test/test_xrvg.rb +3 -0
  57. metadata +16 -5
  58. data/lib/assertion.rb +0 -14
  59. data/lib/attributable.rb +0 -152
data/lib/style.rb CHANGED
@@ -5,6 +5,7 @@ require 'attributable'
5
5
  require 'utils'
6
6
  require 'color'
7
7
 
8
+ module XRVG
8
9
  #
9
10
  # Style class
10
11
  #
@@ -72,4 +73,4 @@ class Style
72
73
  "%strokeopacity%" => strokeopacity} )
73
74
  end
74
75
  end
75
-
76
+ end
data/lib/trace.rb CHANGED
@@ -2,6 +2,7 @@
2
2
  #
3
3
  # Consists in a Trace class, and a Trace global method
4
4
 
5
+ module XRVG
5
6
  # Trace "static" class, to be able to globally inhibit or activate traces
6
7
  # Trace.inihibit
7
8
  # Trace.activate
@@ -26,3 +27,4 @@ def Trace(string)
26
27
  puts string
27
28
  end
28
29
  end
30
+ end
data/lib/utils.rb CHANGED
@@ -11,7 +11,6 @@
11
11
  require 'enumerator'
12
12
  require 'trace'
13
13
  require 'samplation'
14
- require 'assertion'
15
14
 
16
15
  #
17
16
  # Extend class Range with module Samplable and other utilitary methods
@@ -48,6 +47,12 @@ class Range
48
47
  return Range::Angle.clone
49
48
  end
50
49
 
50
+ # return symetric angle between 0 and of size .. 2*size
51
+ # (-size..size)
52
+ def Range.sym( size )
53
+ size = size > 0.0 ? size : -size
54
+ return (-size..size)
55
+ end
51
56
 
52
57
  # compute the symetric of value in context of range
53
58
  # (0.0..1.0).complement( 0.3 ) => 0.7
@@ -57,12 +62,33 @@ class Range
57
62
  return (self.end - diff)
58
63
  end
59
64
 
65
+ # utilitary method to force value to be in range
66
+ # (0.0..1.0).trim( 3.0 ) => 1.0
67
+ # (0.0..1.0).trim( -3.0 ) => 0.0
68
+ def trim( value )
69
+ if value > self.max
70
+ value = self.max
71
+ elsif value < self.min
72
+ value = self.min
73
+ end
74
+ return value
75
+ end
76
+
77
+ # return max value of range
78
+ def max
79
+ return (self.begin > self.end) ? self.begin : self.end
80
+ end
81
+
82
+ # return min value of range
83
+ def min
84
+ return (self.begin < self.end) ? self.begin : self.end
85
+ end
60
86
 
61
87
  # -------------------------------------------------------------
62
88
  # Samplable interface include and overriding
63
89
  # -------------------------------------------------------------
64
- include Samplable
65
- include Splittable
90
+ include XRVG::Samplable
91
+ include XRVG::Splittable
66
92
 
67
93
  # Range base FloatFunctor overloading to do
68
94
  # (1.0..2.0).sample( 0.3 ) => 1.3
@@ -131,7 +157,11 @@ class Range
131
157
  # inverse function of .sample
132
158
  # (1.0..2.0).abscissa( 0.3 ) => 1.3
133
159
  def abscissa( value )
134
- return (value - self.begin) / (self.end - self.begin)
160
+ if self.begin == self.end
161
+ return self.begin
162
+ else
163
+ return (value - self.begin) / (self.end - self.begin)
164
+ end
135
165
  end
136
166
 
137
167
  # return a new range with boundaries translated of "value"
@@ -139,6 +169,56 @@ class Range
139
169
  def translate( value )
140
170
  return (self.begin + value..self.end + value)
141
171
  end
172
+
173
+
174
+ # -------------------------------------------------------------
175
+ # old methods to be refactored
176
+ # -------------------------------------------------------------
177
+
178
+ # deprecated
179
+ #
180
+ # ratios sum must be equal to 1.0
181
+ def multisamples( nsamples, ratios )
182
+ ratiosum = ratios.sum
183
+ samplesum = nsamples.sum
184
+ ratios = ratios.map {|ratio| ratio / ratiosum}
185
+
186
+ rratios = ratios
187
+ index = 0
188
+ ratios.each do |ratio|
189
+ rratios[index] = ratio / nsamples[index]
190
+ index += 1
191
+ end
192
+
193
+ sum = 0.0
194
+ samples = [0.0]
195
+ periodindex = 0
196
+ while sum <= 1.0
197
+ sum += rratios[ periodindex ]
198
+ if sum > 1.0
199
+ break
200
+ end
201
+ samples += [sum]
202
+ periodindex += 1
203
+ if periodindex >= rratios.length
204
+ periodindex = 0.0
205
+ end
206
+ end
207
+ return self.samples( samples )
208
+ end
209
+
210
+ # deprecated
211
+ #
212
+ # TODO : must add gauss parameters
213
+ def randgauss()
214
+ begin
215
+ x1 = 2.0 * Kernel::rand - 1.0
216
+ x2 = 2.0 * Kernel::rand - 1.0
217
+ w = x1 * x1 + x2 * x2
218
+ end while w >= 1.0
219
+ w = Math.sqrt( ( -2.0 * Math.log( w ) ) / w )
220
+ return 1.0/2.0 * ( 1.0 + x1 * w )
221
+ end
142
222
 
143
223
  end
144
224
 
@@ -182,17 +262,10 @@ class Array
182
262
  return self.sum / self.size
183
263
  end
184
264
 
185
- # compute range of an array
186
- # - if proc nil, returns (min..max)
187
- # - else, first compute new array with proc, then (min..max) on this array
265
+ # compute range of an array by returning (min..max)
188
266
  # [1.0, 3.0, 2.0].range => (1.0..3.0)
189
267
  def range( proc=nil )
190
- if not proc
191
- return (self.min..self.max)
192
- else
193
- arraytmp = self.map {|item| item.send( proc )}
194
- return arraytmp.range
195
- end
268
+ return (self.min..self.max)
196
269
  end
197
270
 
198
271
  # alias for sub(2)
@@ -314,8 +387,8 @@ class Array
314
387
  # -------------------------------------------------------------
315
388
  # Samplable interface include and overriding
316
389
  # -------------------------------------------------------------
317
- include Samplable
318
- include Splittable
390
+ include XRVG::Samplable
391
+ include XRVG::Splittable
319
392
 
320
393
  # FloatFunctor overloading to synchronize content sampling and splitting
321
394
  def compute( inputs, type, &block )
@@ -342,8 +415,8 @@ class Float #:nodoc:
342
415
  return ( max - ( self.to_f - min ) )
343
416
  end
344
417
 
345
- def fequal?( other )
346
- return ((self - other).abs < 0.0000000001)
418
+ def fequal?( other, epsilon=0.0000000001 )
419
+ return ((self - other).abs < epsilon)
347
420
  end
348
421
 
349
422
  def randsplit(minsize=0.0)
@@ -354,6 +427,27 @@ class Float #:nodoc:
354
427
  return [min, max]
355
428
  end
356
429
 
430
+ def Float.sort_float_list( floatlist, epsilon=0.0000001 )
431
+ floatlist = floatlist.uniq.sort
432
+ result = [floatlist[0]]
433
+ floatlist[1..-1].each do |item|
434
+ if not item.fequal?( result[-1], epsilon)
435
+ result.push( item )
436
+ end
437
+ end
438
+ return result
439
+ end
440
+
441
+ def Float.floatlist_include?( floatlist, float, epsilon=0.0000001 )
442
+ floatlist.each do |item|
443
+ if item.fequal?( float, epsilon )
444
+ return true
445
+ end
446
+ end
447
+ return false
448
+ end
449
+
450
+
357
451
  end
358
452
 
359
453
 
data/lib/xrvg.rb CHANGED
@@ -3,19 +3,23 @@
3
3
  # Please refer to README for XRVG introduction
4
4
 
5
5
  # XRVG version (used in rakefile)
6
- XRVG_VERSION = "0.0.3"
6
+ XRVG_VERSION = "0.0.4"
7
+
8
+ # XRVG namespace
9
+ module XRVG
10
+ end
7
11
 
8
12
  # Standard Ruby extensions
9
13
  require 'enumerator'
10
14
 
11
15
  # XRVG Infrastructure
12
16
  require 'trace'
13
- require 'assertion'
14
17
 
15
18
  # XRVG new mixins
16
19
  require 'samplation'
17
20
  require 'attributable'
18
21
  require 'interpolation'
22
+ require 'parametriclength'
19
23
 
20
24
  # XRVG base class extensions
21
25
  require 'utils'
@@ -29,8 +33,14 @@ require 'render'
29
33
  require 'bezier'
30
34
 
31
35
  # XRVG extensions
32
- # require 'bezierbuilders'
33
- # require 'beziertools'
34
- # require 'interbezier'
35
- # require 'ondulation'
36
+ require 'fitting'
37
+ require 'bezierbuilders'
38
+ require 'beziermotifs'
39
+ require 'beziertools'
40
+ require 'interbezier'
41
+ # require 'geovariety'
42
+ # require 'spiral'
43
+ # require 'graph'
44
+
45
+
36
46
 
@@ -1,18 +1,33 @@
1
1
  require 'test/unit'
2
2
  require 'attributable'
3
3
  require 'utils'
4
+ include XRVG
4
5
 
5
6
  class AttrClass
6
- include Attributable
7
-
7
+ include XRVG::Attributable
8
+
8
9
  attribute :a, 1.0
9
10
  attribute :b, nil, Float
10
11
  attribute :c
11
12
  end
12
13
 
14
+ class AttrClass1
15
+ include XRVG::Attributable
16
+
17
+ attribute :a, []
18
+
19
+ def adda (value)
20
+ @a.push( value )
21
+ end
22
+ end
13
23
 
14
24
  # Test class
15
25
  class AttributableTest < Test::Unit::TestCase
26
+
27
+ def test_object
28
+ object = Object[]
29
+ end
30
+
16
31
 
17
32
  def test_nominal
18
33
  obj = AttrClass[ :b, 2.0, :c, 3.0 ]
@@ -21,4 +36,21 @@ class AttributableTest < Test::Unit::TestCase
21
36
  assert_equal( 3.0, obj.c)
22
37
  end
23
38
 
39
+ def test_nominal2
40
+ obj1 = AttrClass[ :b, 2.0, :c, 2.0 ]
41
+ obj2 = AttrClass[ :b, 3.0, :c, 3.0 ]
42
+
43
+ assert_equal( 1.0, obj1.a)
44
+ assert_equal( 2.0, obj1.b)
45
+ assert_equal( 3.0, obj2.c)
46
+ end
47
+
48
+ def test_init
49
+ obj1 = AttrClass1[]
50
+ obj2 = AttrClass1[]
51
+ obj2.adda(1)
52
+ assert_equal( [], obj1.a )
53
+ end
54
+
24
55
  end
56
+
data/test/test_bezier.rb CHANGED
@@ -14,6 +14,9 @@ class BezierTest < Test::Unit::TestCase
14
14
  b = Bezier.new( :pieces, [BezierSpline[:raw, V2D[0.0, 1.0], V2D[1.0, 1.0], V2D[0.0, 0.0], V2D[1.0, 0.0]]] )
15
15
  assert_equal( V2D[0.0, 1.0], b.firstpoint )
16
16
 
17
+ b = Bezier[ :pieces, [BezierSpline[:raw, V2D[0.0, 1.0], V2D[1.0, 1.0], V2D[0.0, 0.0], V2D[1.0, 0.0]]]]
18
+ assert_equal( V2D[0.0, 1.0], b.firstpoint )
19
+
17
20
  b = Bezier.single( :raw, V2D[0.0, 1.0], V2D[1.0, 1.0], V2D[0.0, 0.0], V2D[1.0, 0.0] )
18
21
  assert_equal( V2D[0.0, 1.0], b.firstpoint )
19
22
 
@@ -39,6 +42,24 @@ class BezierTest < Test::Unit::TestCase
39
42
  assert_equal( V2D[0.0, 1.0], b.firstpoint )
40
43
  assert( V2D.vequal?( @@bezier.point( 0.1, nil, :parameter ), b.point( 0.1, nil, :parameter ) ) )
41
44
  end
45
+
46
+ def test_builder3
47
+ b = Bezier[ :pieces, [BezierSpline[:vector, V2D[0.0, 1.0], V2D[1.0, 1.0], V2D[0.0, 0.0], V2D[1.0, 0.0]]]]
48
+ assert_equal( V2D[0.0, 1.0], b.firstpoint )
49
+ assert_equal( V2D[0.0, 0.0], b.lastpoint )
50
+
51
+ assert_raise(RuntimeError) {Bezier.raws( 1.0, V2D[1.0, 1.0], V2D[1.0, 0.0], V2D[2.0, 0.0] )}
52
+ end
53
+
54
+ def test_piece_f
55
+ piece = BezierSpline[:vector, V2D[0.0, 1.0], V2D[1.0, 1.0], V2D[0.0, 0.0], V2D[1.0, 0.0]]
56
+ assert_equal( V2D[0.0, 1.0], piece.firstpoint )
57
+ assert_equal( V2D[0.0, 0.0], piece.lastpoint )
58
+ piece = BezierSpline[:vector, V2D[0.0, 1.0], V2D[1.0, 1.0], V2D[0.0, 0.0], V2D[1.0, 0.0]]
59
+ assert_equal( V2D[1.0, 1.0], piece.tangent(0.0) )
60
+ piece = BezierSpline[:vector, V2D[0.0, 1.0], V2D[1.0, 1.0], V2D[0.0, 0.0], V2D[1.0, 0.0]]
61
+ assert_equal( V2D[-2.0, -6.0], piece.acc(0.0) )
62
+ end
42
63
 
43
64
  def test_O
44
65
  assert_equal( [V2D::O, V2D::O, V2D::O, V2D::O], Bezier::O.pointlist )
@@ -88,6 +109,10 @@ class BezierTest < Test::Unit::TestCase
88
109
 
89
110
  assert_equal( [ V2D[0.0, 1.0], V2D[1.0, 1.0], V2D[0.0, 0.0], V2D[1.0, 0.0]], @@multibezier.piece(0.2, :parameter).pointlist )
90
111
  assert_equal( [ V2D[1.0, 0.0], V2D[2.0, 2.0], V2D[1.0, 1.0], V2D[2.0, 0.0]], @@multibezier.piece(1.2, :parameter).pointlist )
112
+
113
+ assert_raise(RuntimeError) {@@multibezier.pointlist(:toto)}
114
+ assert_raise(RuntimeError) {@@multibezier.piece(0.2,:toto).pointlist}
115
+
91
116
  end
92
117
 
93
118
  def test_firstpoint
@@ -105,6 +130,24 @@ class BezierTest < Test::Unit::TestCase
105
130
  assert_equal( V2D[1.0, 0.0], beziers[1].firstpoint )
106
131
  end
107
132
 
133
+ def test_bezier_index
134
+ assert_equal( V2D[0.0, 1.0], @@multibezier.bezier(0).firstpoint )
135
+ assert_equal( V2D[1.0, 0.0], @@multibezier.bezier(1).firstpoint )
136
+ end
137
+
138
+ def test_data
139
+ assert_equal( [@@piece], @@bezier.data )
140
+ end
141
+
142
+ def test_subbezier
143
+ assert_equal( 1, @@multibezier.subbezier(0.0,0.1).piecenumber )
144
+ assert_equal( 2, @@multibezier.subbezier(0.1,0.6).piecenumber )
145
+
146
+ pieces = [[:raw, V2D[0.0, 1.0], V2D[1.0, 1.0], V2D[0.0, 0.0], V2D[1.0, 0.0] ],
147
+ [:raw, V2D[1.0, 0.0], V2D[2.0, 2.0], V2D[1.0, 1.0], V2D[2.0, 0.0] ],
148
+ [:raw, V2D[2.0, 0.0], V2D[2.0, 2.0], V2D[1.0, 1.0], V2D[3.0, 0.0] ]]
149
+ assert_equal( 3, Bezier.multi( pieces ).subbezier(0.1,0.9).piecenumber )
150
+ end
108
151
 
109
152
  def test_computelength
110
153
  assert( (1.0 - Bezier.raw( V2D[0.0, 0.0], V2D[1.0, 0.0], V2D[0.0, 0.0], V2D[1.0, 0.0] ).length()).abs < 0.00001 )
@@ -151,8 +194,23 @@ class BezierTest < Test::Unit::TestCase
151
194
  assert( V2D.vequal?( V2D[0.0, 0.0], container ) )
152
195
  end
153
196
 
154
- def test_ranges
155
- assert_equal( [(0.0..1.0), (1.0..2.0)], @@multibezier.ranges )
197
+ def test_frame
198
+ frame = @@bezier.frame( 0.0 )
199
+ assert_equal( @@bezier.point( 0.0 ), frame.center )
200
+ assert_equal( @@bezier.tangent( 0.0 ), frame.vector )
201
+ end
202
+
203
+ def test_reverse
204
+ assert_equal( [V2D[1.0, 0.0], V2D[0.0, 0.0], V2D[1.0, 1.0], V2D[0.0, 1.0]], @@bezier.reverse.pointlist )
205
+ end
206
+
207
+ def test_translate
208
+ assert_equal( [V2D[1.0, 4.0], V2D[2.0, 4.0], V2D[1.0, 3.0], V2D[2.0, 3.0] ], @@bezier.translate( V2D[1.0,3.0] ).pointlist )
209
+ end
210
+
211
+ def test_similar
212
+ assert_equal( [V2D[1.0, 4.0], V2D[2.0, 4.0], V2D[1.0, 3.0], V2D[2.0, 3.0] ], @@bezier.similar( (V2D[1.0,4.0]..V2D[2.0,3.0]) ).pointlist )
213
+ assert_raise(RuntimeError) {(@@bezier + @@bezier.reverse).similar( (V2D::O..V2D::X) )}
156
214
  end
157
215
 
158
216
  def test_split1
@@ -165,6 +223,39 @@ class BezierTest < Test::Unit::TestCase
165
223
  assert( V2D.vequal?( V2D::O, Bezier::O.split( 0.5,0.8 ).lastpoint ) )
166
224
  end
167
225
 
226
+ def test_splitblock
227
+ result = []
228
+ @@beziersym.splits( 2 ) do |subbezier|
229
+ result << subbezier
230
+ end
231
+ assert_equal( 2, result.length )
232
+ end
233
+
234
+ def test_svg
235
+ assert_equal( "<path d=\"M 0.0,1.0C 1.0,1.0 0.0,0.0 1.0,0.0\"/>", @@bezier.svg )
236
+ assert_equal( "<path d=\"M 0.0,1.0C 1.0,1.0 0.0,0.0 1.0,0.0C 0.0,0.0 1.0,1.0 0.0,1.0 z\"/>", (@@bezier + @@bezier.reverse).svg )
237
+ end
238
+
239
+ def test_gdebug
240
+ require 'render'
241
+ render = SVGRender[]
242
+ @@bezier.gdebug( render )
243
+ end
244
+
245
+ def test_piecelength
246
+ assert_equal( [0.0,1.0], @@bezier.piecelengths )
247
+ assert_equal( [0.0,0.5,1.0], (@@bezier + @@bezier.reverse).piecelengths )
248
+ end
249
+
250
+ def test_length_parameter_mapping
251
+ assert_equal( [1,0.0], (@@bezier + @@bezier.reverse).length_parameter_mapping(0.5, :left) )
252
+ assert_raise(RuntimeError) {@@multibezier.length_parameter_mapping(1.1, :left)}
253
+ end
254
+
255
+ def test_filter
256
+ assert( V2D.vequal?( V2D[0.5, 0.5], @@beziersym.filter(:point).sample( 0.5 ) ) )
257
+ end
258
+
168
259
 
169
260
  end
170
261