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/CHANGES +34 -0
- data/README +2 -2
- data/Rakefile +111 -29
- data/examples/bezierbasic.rb +7 -0
- data/examples/bezierbasicvector.rb +7 -0
- data/examples/foreach.rb +1 -1
- data/examples/geodash.rb +8 -0
- data/examples/geodash2.rb +8 -0
- data/examples/hellocrown.rb +1 -1
- data/examples/hellocrown2.rb +1 -1
- data/examples/hellocrownrecurse.rb +1 -1
- data/examples/multibezierbasic.rb +8 -0
- data/examples/randomdash.rb +8 -0
- data/examples/range_examples.rb +16 -0
- data/examples/range_examples2.rb +10 -0
- data/examples/sample.rb +4 -2
- data/examples/simpledash.rb +8 -0
- data/examples/uplets.rb +1 -1
- data/lib/bezier.rb +461 -0
- data/lib/bezierspline.rb +266 -0
- data/lib/color.rb +44 -5
- data/lib/geometry2D.rb +116 -90
- data/lib/interpolation.rb +4 -2
- data/lib/samplation.rb +16 -10
- data/lib/shape.rb +101 -53
- data/lib/style.rb +13 -12
- data/lib/utils.rb +4 -3
- data/lib/xrvg.rb +2 -3
- data/test/test_bezier.rb +151 -0
- data/test/test_geometry2D.rb +38 -25
- data/test/test_shape.rb +67 -0
- data/test/test_utils.rb +45 -0
- metadata +28 -14
- data/examples/helloworld.rb +0 -5
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
|
-
|
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
|
-
|
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.
|
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
|
-
|
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
|
-
|
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 /
|
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 :
|
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[ :
|
222
|
+
# line = Line[ :points, [V2D::O, V2D::X] ]
|
183
223
|
class Line < Curve
|
184
|
-
attribute :
|
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
|
-
|
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
|
-
|
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[ :
|
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 == @
|
216
|
-
|
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
|
-
|
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,
|
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
|
-
|
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
|
283
|
+
# simply call V2D.viewbox on :points
|
238
284
|
def viewbox
|
239
|
-
return
|
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 :
|
290
|
+
# return a new line with every point of :points translated
|
245
291
|
def translate( v )
|
246
|
-
return Line[ :
|
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 :
|
297
|
+
# return a new line with :points reversed
|
252
298
|
def reverse
|
253
|
-
return Line[ :
|
299
|
+
return Line[ :points, @points.reverse ]
|
254
300
|
end
|
255
301
|
|
256
302
|
# return line svg description
|
257
303
|
def svg
|
258
|
-
path = "M #{
|
259
|
-
|
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,
|
319
|
+
# attribute :center, V2D[0.0,0.0]
|
274
320
|
# attribute :radius, 1.0
|
275
321
|
# = Example
|
276
|
-
# c = Circle[ :center,
|
322
|
+
# c = Circle[ :center, V2D::O, :radius, 1.0 ] # equiv Circle[]
|
277
323
|
class Circle < Curve
|
278
|
-
attribute :center,
|
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
|
-
|
324
|
-
|
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
|
30
|
-
if
|
31
|
-
|
29
|
+
def fillopacity()
|
30
|
+
if @fill.is_a? Color
|
31
|
+
return @fill.a
|
32
32
|
end
|
33
|
-
|
33
|
+
return 1.0
|
34
34
|
end
|
35
35
|
|
36
|
-
def
|
37
|
-
if
|
38
|
-
|
36
|
+
def strokeopacity()
|
37
|
+
if @stroke.is_a? Color
|
38
|
+
return @stroke.a
|
39
39
|
end
|
40
|
-
|
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%" =>
|
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 -
|
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.
|
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
|
-
|
30
|
-
# require 'bezierspline'
|
29
|
+
require 'bezier'
|
31
30
|
|
32
31
|
# XRVG extensions
|
33
32
|
# require 'bezierbuilders'
|
data/test/test_bezier.rb
ADDED
@@ -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
|
+
|