xrvg 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/lib/samplation.rb CHANGED
@@ -51,18 +51,18 @@ module FloatFunctor
51
51
  end
52
52
 
53
53
  # hook for Array
54
- def compute( indata, type )
55
- return self.apply( self.modify( indata ), type )
54
+ def compute( indata, type, &block )
55
+ return self.apply( self.modify( indata ), type, &block )
56
56
  end
57
57
 
58
58
  # hook for rand()
59
59
  def process( indata, type, &block )
60
- outdata = self.compute( indata, type )
61
60
  if not block
61
+ outdata = self.compute( indata, type )
62
62
  # Trace("Samplable#trigger object #{self.inspect} indata #{indata.inspect} outdata #{outdata.inspect}")
63
63
  return outdata
64
64
  else
65
- outdata.foreach(nil,&block)
65
+ self.compute( indata, type, &block )
66
66
  end
67
67
  end
68
68
 
@@ -101,6 +101,7 @@ module FloatFunctor
101
101
  # it is a registration interface
102
102
  #
103
103
  # must not be overloaded
104
+
104
105
  # must be refactored with some meta hooks
105
106
  def applyhash
106
107
  result = {}
@@ -110,12 +111,12 @@ module FloatFunctor
110
111
  end
111
112
 
112
113
  # must not be overloaded (apart from Samplable containers)
113
- def apply( data, type )
114
+ def apply( data, type, &block )
114
115
  @applyhash = self.applyhash
115
116
  if not @applyhash.key? type
116
117
  Kernel::Raise("FloatFunctor::apply no regsitration for type #{type} and object #{object.inspect}")
117
118
  else
118
- return self.send(@applyhash[type], data )
119
+ return self.send(@applyhash[type], data, &block )
119
120
  end
120
121
  end
121
122
 
@@ -250,12 +251,17 @@ module Samplable
250
251
  # to be overloaded if needed
251
252
  #
252
253
  # called by FloatFunctor apply method
253
- def apply_samples( inputs )
254
- return inputs.map {|abs| self.apply_sample( abs ) }
254
+ def apply_samples( inputs, &block )
255
+ if not block
256
+ return inputs.map {|abs| self.apply_sample( abs ) }
257
+ else
258
+ container = self.apply_sample( inputs[0] ); yield container;
259
+ inputs[1..-1].each {|abs| yield self.apply_sample( abs, container ) }
260
+ end
255
261
  end
256
262
 
257
263
  # to be overloaded if needed
258
- def apply_sample( abs )
264
+ def apply_sample( abs, container=nil )
259
265
  return abs
260
266
  end
261
267
 
@@ -296,7 +302,7 @@ module Splittable
296
302
 
297
303
  # must not be overriden
298
304
  def split( abs1, abs2 )
299
- return self.apply( self.filter( [abs1,abs2] ), :split ).pop
305
+ return self.apply( self.modify( [abs1,abs2] ), :split ).pop
300
306
  end
301
307
 
302
308
  # to be overloaded if needed
data/lib/shape.rb CHANGED
@@ -74,7 +74,7 @@ class Curve < Shape
74
74
  # abstract
75
75
  #
76
76
  # must be defined
77
- def point( abscissa )
77
+ def point( abscissa, container=nil )
78
78
  Kernel::raise("Curve::point must be redefined in subclasses")
79
79
  end
80
80
 
@@ -83,7 +83,7 @@ class Curve < Shape
83
83
  # abstract
84
84
  #
85
85
  # must be defined
86
- def tangent( abscissa )
86
+ def tangent( abscissa, container=nil )
87
87
  Kernel::raise("Curve::tangent must be redefined in subclasses")
88
88
  end
89
89
 
@@ -92,28 +92,10 @@ class Curve < Shape
92
92
  # abstract
93
93
  #
94
94
  # must be defined
95
- def acc( abscissa )
95
+ def acc( abscissa, container=nil )
96
96
  Kernel::raise("Curve::acc must be redefined in subclasses")
97
97
  end
98
98
 
99
- # must compute the rotation at curve abscissa
100
- #
101
- # abstract
102
- #
103
- # must be defined
104
- def rotation( abscissa )
105
- Kernel::raise("Curve::rotation must be redefined in subclasses")
106
- end
107
-
108
- # must compute the scale at curve abscissa
109
- #
110
- # abstract
111
- #
112
- # must be defined
113
- def scale( abscissa )
114
- Kernel::raise("Curve::scale must be redefined in subclasses")
115
- end
116
-
117
99
  # must return the length at abscissa, or total length if abscissa nil
118
100
  #
119
101
  # abstract
@@ -127,10 +109,61 @@ class Curve < Shape
127
109
  def default_style
128
110
  return Style[ :stroke, Color.black, :strokewidth, self.length / 100.0 ]
129
111
  end
112
+
113
+ # compute the rotation at curve abscissa, or directly from tangent (for frame computation speed up),
114
+ # as angle between tangent0 angle and tangent( abscissa ) (or tangent) angle
115
+ def rotation( abscissa, tangent=nil )
116
+ if not tangent
117
+ tangent = self.tangent( abscissa )
118
+ end
119
+ return (tangent.angle - self.tangent0_angle)
120
+ end
121
+
122
+ # must compute the scale at curve abscissa, or directly from tangent (for frame computation speed up)
123
+ # as ratio between tangent0 size and tangent( abscissa ) (or tangent) size
124
+ def scale( abscissa, tangent=nil )
125
+ if not tangent
126
+ tangent = self.tangent( abscissa )
127
+ end
128
+ result = 0.0
129
+ if not self.tangent0_length == 0.0
130
+ result = (tangent.r - self.tangent0_length)
131
+ end
132
+ return result
133
+ end
134
+
135
+ def tangent0
136
+ if not @tangent0
137
+ @tangent0 = self.tangent( 0.0 )
138
+ end
139
+ return @tangent0
140
+ end
141
+
142
+ # TODO : must be cached in vector
143
+ def tangent0_angle
144
+ if not @tangent0_angle
145
+ @tangent0_angle = self.tangent0.angle
146
+ end
147
+ return @tangent0_angle
148
+ end
149
+
150
+ # TODO : must be cached in vector
151
+ def tangent0_length
152
+ if not @tangent0_length
153
+ @tangent0_length = self.tangent0.r
154
+ end
155
+ return @tangent0_length
156
+ end
130
157
 
158
+ # compute frame vector at abscissa t, that is [curve.point( t ), curve.tangent( t ) ]
159
+ def framev( t )
160
+ return [curve.point( t ), curve.tangent( t ) ]
161
+ end
162
+
131
163
  # compute frame at abscissa t
132
164
  def frame( t )
133
- return Frame[ :center, self.point( t ), :vector, self.tangent( t ), :rotation, self.rotation( t ), :scale, self.scale( t ) ]
165
+ point, tangent = self.framev( t )
166
+ return Frame[ :center, point, :vector, tangent, :rotation, self.rotation( nil, tangent ), :scale, self.scale( nil, tangent ) ]
134
167
  end
135
168
 
136
169
  # compute normal at abscissa t
@@ -149,10 +182,11 @@ class Curve < Shape
149
182
 
150
183
  # compute curvature at abscissa t
151
184
  def curvature( t )
152
- if self.acc_normal( t ) == 0.0
185
+ acc_normal = self.acc_normal( t )
186
+ if acc_normal == 0.0
153
187
  return 0.0
154
188
  end
155
- return 1.0 / (self.tangent( t ).r / self.acc_normal( t ))
189
+ return 1.0 / (self.tangent( t ).r / acc_normal )
156
190
  end
157
191
 
158
192
  # shortcut method to map frames from abscissas
@@ -171,17 +205,23 @@ class Curve < Shape
171
205
  return abscissas.map { |abscissa| self.tangent( abscissa ) }
172
206
  end
173
207
 
208
+ # shortcut method, map of normal
209
+ def normals( indexes )
210
+ return indexes.map {|i| self.normal( i )}
211
+ end
212
+
174
213
  end
175
214
 
176
215
  # Line class
177
216
  # = Intro
178
217
  # Used to draw polylines and polygons
179
218
  # = Attributes
180
- # attribute :exts, [Point[0.0, 0.0], Point[1.0, 1.0]]
219
+ # attribute :points, [V2D[0.0, 0.0], V2D[1.0, 1.0]]
220
+ # WARNING : getter "points" is not defined, because is defined as Curve.points( abscissa ) !!!
181
221
  # = Example
182
- # line = Line[ :exts, [Point::O, Point::X] ]
222
+ # line = Line[ :points, [V2D::O, V2D::X] ]
183
223
  class Line < Curve
184
- attribute :exts, [Point[0.0, 0.0], Point[1.0, 1.0]]
224
+ attribute :points, [V2D[0.0, 0.0], V2D[1.0, 1.0]]
185
225
 
186
226
  def initialize (*args) #:nodoc:
187
227
  super( *args )
@@ -191,7 +231,7 @@ class Line < Curve
191
231
  def init_tangents #:nodoc:
192
232
  index = 0
193
233
  @tangents = Array.new
194
- self.exts.pairs { |p1, p2|
234
+ @points.pairs { |p1, p2|
195
235
  @tangents[ index ] = (p2-p1).norm
196
236
  index += 1
197
237
  }
@@ -201,7 +241,7 @@ class Line < Curve
201
241
  def length
202
242
  if not @length
203
243
  @length = 0.0
204
- self.exts.pairs do |p1, p2|
244
+ @points.pairs do |p1, p2|
205
245
  @length += (p1 - p2).r
206
246
  end
207
247
  end
@@ -209,54 +249,60 @@ class Line < Curve
209
249
  end
210
250
 
211
251
  # compute line point at abscissa
212
- # Line[ :exts, [Point::O, Point::X] ].point( 0.3 ) => Vector[0.0,0.3]
213
- def point (abscissa)
252
+ # Line[ :points, [V2D::O, V2D::X] ].point( 0.3 ) => V2D[0.0,0.3]
253
+ def point (abscissa, container=nil)
254
+ container ||= V2D[]
214
255
  piece1 = abscissa.to_int
215
- if piece1 == @exts.size - 1
216
- return @exts[-1]
256
+ if piece1 == @points.size - 1
257
+ container.xy = @points[-1]
258
+ else
259
+ abscissa -= piece1
260
+ cpoints = @points.slice( piece1, 2 )
261
+ container.xy = [(cpoints[0].x..cpoints[1].x).sample( abscissa ),
262
+ (cpoints[0].y..cpoints[1].y).sample( abscissa )]
217
263
  end
218
- abscissa -= piece1
219
- cexts = self.exts.slice( piece1, 2 )
220
- return (cexts[0]..cexts[1]).sample( abscissa )
264
+ return container
221
265
  end
222
266
 
223
267
  # compute line frame at abscissa
224
268
  #
225
269
  # for the moment, frame rotation is always 0.0, and scale always 1.0
226
270
  def frame (abscissa)
227
- return Frame[ :center, self.point( abscissa ), :vector, Vector[ 0.0, 0.0 ], :rotation, 0.0, :scale, 1.0 ]
271
+ return Frame[ :center, self.point( abscissa ), :vector, V2D[ 0.0, 0.0 ], :rotation, 0.0, :scale, 1.0 ]
228
272
  end
229
273
 
230
274
  # compute line tangent at abscissa
231
- def tangent (abscissa)
232
- return @tangents[abscissa.to_int].dup
275
+ def tangent (abscissa, container=nil)
276
+ container ||= V2D[]
277
+ container.xy = @tangents[abscissa.to_int]
278
+ return container
233
279
  end
234
280
 
235
281
  # compute viewbox of the line
236
282
  #
237
- # simply call Point.viewbox on :exts
283
+ # simply call V2D.viewbox on :points
238
284
  def viewbox
239
- return Point.viewbox( self.exts )
285
+ return V2D.viewbox( @points )
240
286
  end
241
287
 
242
288
  # translate a line of v offset, v being a vector
243
289
  #
244
- # return a new line with every point of :exts translated
290
+ # return a new line with every point of :points translated
245
291
  def translate( v )
246
- return Line[ :exts, @exts.map {|ext| ext.translate( v )} ]
292
+ return Line[ :points, @points.map {|ext| ext.translate( v )} ]
247
293
  end
248
294
 
249
295
  # reverse a line
250
296
  #
251
- # return a new line with :exts reversed
297
+ # return a new line with :points reversed
252
298
  def reverse
253
- return Line[ :exts, @exts.reverse ]
299
+ return Line[ :points, @points.reverse ]
254
300
  end
255
301
 
256
302
  # return line svg description
257
303
  def svg
258
- path = "M #{exts[0].x} #{exts[0].y} "
259
- exts[1..-1].each { |p|
304
+ path = "M #{points[0].x} #{points[0].y} "
305
+ @points[1..-1].each { |p|
260
306
  path += "L #{p.x} #{p.y}"
261
307
  }
262
308
  return "<path d=\"" + path + "\"/>"
@@ -270,12 +316,12 @@ end
270
316
  # = Intro
271
317
  # define a circle curve
272
318
  # = Attributes
273
- # attribute :center, Vector[0.0,0.0]
319
+ # attribute :center, V2D[0.0,0.0]
274
320
  # attribute :radius, 1.0
275
321
  # = Example
276
- # c = Circle[ :center, Point::O, :radius, 1.0 ] # equiv Circle[]
322
+ # c = Circle[ :center, V2D::O, :radius, 1.0 ] # equiv Circle[]
277
323
  class Circle < Curve
278
- attribute :center, Vector[0.0,0.0]
324
+ attribute :center, V2D[0.0,0.0]
279
325
  attribute :radius, 1.0
280
326
 
281
327
  # compute length of the circle
@@ -318,10 +364,12 @@ class Circle < Curve
318
364
  end
319
365
 
320
366
  # compute point at abscissa
321
- def point (abscissa)
367
+ def point (abscissa, container=nil)
322
368
  angle = Range::Angle.sample( abscissa )
323
- return Point[ self.cx + self.radius * Math.cos( angle ),
324
- self.cy + self.radius * Math.sin( angle )]
369
+ container ||=V2D[]
370
+ container.x = self.cx + self.radius * Math.cos( angle )
371
+ container.y = self.cy + self.radius * Math.sin( angle )
372
+ return container
325
373
  end
326
374
 
327
375
  # compute tangent at abscissa
data/lib/style.rb CHANGED
@@ -19,27 +19,28 @@ require 'color'
19
19
  # render.add( Circle[], Style[ :stroke, Color.red ] )
20
20
  class Style
21
21
  include Attributable
22
- attribute :opacity, 1.0
22
+ # attribute :opacity, 1.0
23
23
  attribute :fill, "none", [String, Color, Gradient]
24
- attribute :fillopacity, 1.0
24
+ # attribute :fillopacity, 1.0
25
25
  attribute :stroke, "none", [String, Color, Gradient]
26
26
  attribute :strokewidth, 1.0
27
- attribute :strokeopacity, 1.0
27
+ # attribute :strokeopacity, 1.0
28
28
 
29
- def fill=( color )
30
- if color.is_a? Color
31
- self.fillopacity = color.a
29
+ def fillopacity()
30
+ if @fill.is_a? Color
31
+ return @fill.a
32
32
  end
33
- @fill = color
33
+ return 1.0
34
34
  end
35
35
 
36
- def stroke=( color )
37
- if color.is_a? Color
38
- self.strokeopacity = color.a
36
+ def strokeopacity()
37
+ if @stroke.is_a? Color
38
+ return @stroke.a
39
39
  end
40
- @stroke = color
40
+ return 1.0
41
41
  end
42
42
 
43
+
43
44
  def svgfill
44
45
  if fill.is_a? Color
45
46
  return fill.svg
@@ -63,7 +64,7 @@ class Style
63
64
  def svgline
64
65
  template = 'style="opacity:%opacity%;fill:%fill%;fill-opacity:%fillopacity%;stroke:%stroke%;stroke-width:%strokewidth%;stroke-opacity:%strokeopacity%"'
65
66
 
66
- return template.subreplace( {"%opacity%" => opacity,
67
+ return template.subreplace( {"%opacity%" => 1.0,
67
68
  "%fill%" => svgfill,
68
69
  "%fillopacity%" => fillopacity,
69
70
  "%stroke%" => svgstroke,
data/lib/utils.rb CHANGED
@@ -51,9 +51,10 @@ class Range
51
51
 
52
52
  # compute the symetric of value in context of range
53
53
  # (0.0..1.0).complement( 0.3 ) => 0.7
54
+ # (1.0..2.0).complement( 1.3 ) => 1.7
54
55
  def complement( value )
55
56
  diff = value - self.begin
56
- return (self.end - value)
57
+ return (self.end - diff)
57
58
  end
58
59
 
59
60
 
@@ -317,8 +318,8 @@ class Array
317
318
  include Splittable
318
319
 
319
320
  # FloatFunctor overloading to synchronize content sampling and splitting
320
- def compute( inputs, type )
321
- return self.map {|v| v.compute( inputs, type )}.forzip
321
+ def compute( inputs, type, &block )
322
+ return self.map {|v| v.compute( inputs, type )}.forzip(nil,&block)
322
323
  end
323
324
 
324
325
  end
data/lib/xrvg.rb CHANGED
@@ -3,7 +3,7 @@
3
3
  # Please refer to README for XRVG introduction
4
4
 
5
5
  # XRVG version (used in rakefile)
6
- XRVG_VERSION = "0.0.1"
6
+ XRVG_VERSION = "0.0.2"
7
7
 
8
8
  # Standard Ruby extensions
9
9
  require 'enumerator'
@@ -26,8 +26,7 @@ require 'color'
26
26
  require 'frame'
27
27
  require 'shape'
28
28
  require 'render'
29
- # require 'bezier'
30
- # require 'bezierspline'
29
+ require 'bezier'
31
30
 
32
31
  # XRVG extensions
33
32
  # require 'bezierbuilders'
@@ -0,0 +1,151 @@
1
+ require 'test/unit'
2
+ require 'bezier'
3
+
4
+ class BezierTest < Test::Unit::TestCase
5
+
6
+ @@piece = [ :raw, V2D[0.0, 1.0], V2D[1.0, 1.0], V2D[0.0, 0.0], V2D[1.0, 0.0] ]
7
+ @@bezier = Bezier.single( *@@piece )
8
+ @@beziersym = Bezier.raw( V2D[0.0, 0.0], V2D[1.0, 0.0], V2D[0.0, 1.0], V2D[1.0, 1.0] )
9
+ @@pieces = [[:raw, V2D[0.0, 1.0], V2D[1.0, 1.0], V2D[0.0, 0.0], V2D[1.0, 0.0] ],
10
+ [:raw, V2D[1.0, 0.0], V2D[2.0, 2.0], V2D[1.0, 1.0], V2D[2.0, 0.0] ]]
11
+ @@multibezier = Bezier.multi( @@pieces )
12
+
13
+ def test_builder
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
+ assert_equal( V2D[0.0, 1.0], b.firstpoint )
16
+
17
+ 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
+ assert_equal( V2D[0.0, 1.0], b.firstpoint )
19
+
20
+ b = Bezier.raw( V2D[0.0, 1.0], V2D[1.0, 1.0], V2D[0.0, 0.0], V2D[1.0, 0.0] )
21
+ assert_equal( V2D[0.0, 1.0], b.firstpoint )
22
+
23
+ b = Bezier.vector( V2D[0.0, 1.0], V2D[1.0, 1.0], V2D[0.0, 0.0], V2D[1.0, 0.0] )
24
+ assert_equal( V2D[0.0, 1.0], b.firstpoint )
25
+
26
+ b = Bezier.multi( [@@piece] )
27
+ assert_equal( V2D[0.0, 1.0], b.firstpoint )
28
+
29
+ b = Bezier.multi( [@@piece,@@piece] )
30
+ assert_equal( V2D[0.0, 1.0], b.firstpoint )
31
+ end
32
+
33
+ def test_O
34
+ assert_equal( [V2D::O, V2D::O, V2D::O, V2D::O], Bezier::O.pointlist )
35
+ end
36
+
37
+ def test_piece
38
+ assert_equal( V2D[0.0, 1.0], @@multibezier.piece( 0 ).firstpoint )
39
+ assert_equal( V2D[1.0, 0.0], @@multibezier.piece( 1 ).firstpoint )
40
+
41
+ assert_equal( V2D[0.0, 1.0], @@multibezier.piece( 0.2 ).firstpoint )
42
+ assert_equal( V2D[1.0, 0.0], @@multibezier.piece( 0.7 ).firstpoint )
43
+
44
+ assert_equal( V2D[0.0, 1.0], @@multibezier.piece( 0.2, :parameter ).firstpoint )
45
+ assert_equal( V2D[0.0, 1.0], @@multibezier.piece( 0.7, :parameter ).firstpoint )
46
+ assert_equal( V2D[1.0, 0.0], @@multibezier.piece( 1.2, :parameter ).firstpoint )
47
+ end
48
+
49
+ def test_piecenumber
50
+ assert_equal( 1, @@bezier.piecenumber )
51
+ assert_equal( 2, @@multibezier.piecenumber )
52
+ end
53
+
54
+ def test_viewbox
55
+ assert_equal( [0.0, 0.0, 1.0, 1.0], @@bezier.viewbox )
56
+ end
57
+
58
+ def test_pointlist
59
+ assert_equal( [ V2D[0.0, 1.0], V2D[1.0, 1.0], V2D[0.0, 0.0], V2D[1.0, 0.0],
60
+ V2D[1.0, 0.0], V2D[2.0, 2.0], V2D[1.0, 1.0], V2D[2.0, 0.0] ], @@multibezier.pointlist() )
61
+ assert_equal( [ V2D[0.0, 1.0], V2D[1.0, 1.0], V2D[0.0, 0.0], V2D[1.0, 0.0],
62
+ V2D[1.0, 0.0], V2D[2.0, 2.0], V2D[1.0, 1.0], V2D[2.0, 0.0] ], @@multibezier.pointlist(:raw) )
63
+ assert_equal( [ V2D[0.0, 1.0], V2D[1.0, 0.0], V2D[1.0, 0.0], V2D[-1.0, 0.0],
64
+ V2D[1.0, 0.0], V2D[1.0, 2.0], V2D[2.0, 0.0], V2D[-1.0, 1.0] ], @@multibezier.pointlist(:vector) )
65
+
66
+ 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).pointlist() )
67
+ 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).pointlist() )
68
+
69
+ 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).pointlist(:raw) )
70
+ 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).pointlist(:raw) )
71
+
72
+ assert_equal( [ V2D[0.0, 1.0], V2D[1.0, 0.0], V2D[1.0, 0.0], V2D[-1.0, 0.0]], @@multibezier.piece(0).pointlist(:vector) )
73
+ assert_equal( [ V2D[1.0, 0.0], V2D[1.0, 2.0], V2D[2.0, 0.0], V2D[-1.0, 1.0]], @@multibezier.piece(1).pointlist(:vector) )
74
+
75
+ 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).pointlist(:raw) )
76
+ assert_equal( [ V2D[1.0, 0.0], V2D[2.0, 2.0], V2D[1.0, 1.0], V2D[2.0, 0.0]], @@multibezier.piece(0.8).pointlist(:raw) )
77
+
78
+ 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 )
79
+ 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 )
80
+ end
81
+
82
+ def test_firstpoint
83
+ assert_equal( V2D[0.0, 1.0], @@multibezier.firstpoint )
84
+ end
85
+
86
+ def test_lastpoint
87
+ assert_equal( V2D[2.0, 0.0], @@multibezier.lastpoint )
88
+ end
89
+
90
+ def test_beziers
91
+ beziers = @@multibezier.beziers
92
+ assert_equal( 2, beziers.length )
93
+ assert_equal( V2D[0.0, 1.0], beziers[0].firstpoint )
94
+ assert_equal( V2D[1.0, 0.0], beziers[1].firstpoint )
95
+ end
96
+
97
+
98
+ def test_computelength
99
+ 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 )
100
+ end
101
+
102
+
103
+ def test_point
104
+ assert( V2D.vequal?( V2D[0.5, 0.5], @@beziersym.point( 0.5 ) ) )
105
+ end
106
+
107
+
108
+ def test_point_boundary
109
+ assert( V2D.vequal?( @@beziersym.point( 0.0 ), @@beziersym.point( -1.0 ) ) )
110
+ assert( V2D.vequal?( @@beziersym.point( 1.0 ), @@beziersym.point( 2.0 ) ) )
111
+ end
112
+
113
+ def test_parameter
114
+ assert( V2D.vequal?( @@beziersym.piece(0).point( 0.1 ), @@beziersym.point( 0.1, nil, :parameter ) ) )
115
+ end
116
+
117
+ def test_tangent
118
+ assert( V2D.vequal?( V2D[0.0, 0.5], @@beziersym.tangent( 0.5 ) ) )
119
+ end
120
+
121
+ def test_acc
122
+ assert( V2D.vequal?( V2D[0.0, 0.0], @@beziersym.acc( 0.5 ) ) )
123
+ end
124
+
125
+ def test_point2
126
+ container = V2D[0.0,0.0]
127
+ assert( V2D.vequal?( V2D[0.5, 0.5], @@beziersym.point( 0.5, container ) ) )
128
+ assert( V2D.vequal?( V2D[0.5, 0.5], container ) )
129
+ end
130
+
131
+ def test_tangent2
132
+ container = V2D[0.0,0.0]
133
+ assert( V2D.vequal?( V2D[0.0, 0.5], @@beziersym.tangent( 0.5, container ) ) )
134
+ assert( V2D.vequal?( V2D[0.0, 0.5], container ) )
135
+ end
136
+
137
+ def test_tangent3
138
+ container = V2D[0.0,0.0]
139
+ assert( V2D.vequal?( V2D[0.0, 0.0], @@beziersym.acc( 0.5, container ) ) )
140
+ assert( V2D.vequal?( V2D[0.0, 0.0], container ) )
141
+ end
142
+
143
+ def test_ranges
144
+ assert_equal( [(0.0..1.0), (1.0..2.0)], @@multibezier.ranges )
145
+ end
146
+
147
+ end
148
+
149
+
150
+
151
+