xrvg 0.0.1 → 0.0.2

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