xrvg 0.0.6 → 0.0.7

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/shape.rb DELETED
@@ -1,421 +0,0 @@
1
- # shape.rb file
2
- # See
3
- # - Shape interface
4
- # - Curve interface
5
- # - Line class
6
- # - Circle class
7
- require 'utils'
8
- require 'frame'
9
- require 'geometry2D'
10
-
11
-
12
- module XRVG
13
- # Shape abstract interface
14
- # = Intro
15
- # To provide a set of services a shape class must provide
16
- class Shape
17
- include Attributable
18
-
19
- # must return the contour of the shape, of Curve type
20
- #
21
- # abstract
22
- #
23
- # not yet used
24
- def contour( *args )
25
- raise NotImplementedError.new("#{self.class.name}#contour is an abstract method.")
26
- end
27
-
28
- # must return the svg description of the shape
29
- #
30
- # abstract
31
- #
32
- # must be defined
33
- def svg()
34
- raise NotImplementedError.new("#{self.class.name}#svg is an abstract method.")
35
- end
36
-
37
- # must return the enclosing box of the shape, that is [xmin, ymin, xmax, ymax]
38
- #
39
- # abstract
40
- #
41
- # must be defined
42
- def viewbox()
43
- raise NotImplementedError.new("#{self.class.name}#viewbox is an abstract method.")
44
- end
45
-
46
- # compute size of the shape, from viewbox
47
- def size()
48
- xmin, ymin, xmax, ymax = self.viewbox
49
- return [xmax-xmin, ymax-ymin]
50
- end
51
-
52
- # return the default style for a Shape instance
53
- #
54
- # is done on instance, because for Curve for example, strokewidth is proportional to length
55
- def default_style()
56
- return Style[:fill, Color.black ]
57
- end
58
-
59
- # compute the "surface" of the viewbox of the shape
60
- #
61
- # use size method
62
- def surface
63
- width, height = self.size
64
- return width * height
65
- end
66
-
67
- end
68
-
69
- # Curve abstract interface
70
- # = Intro
71
- # To define a set of services a curve class must provide
72
- class Curve < Shape
73
- # must compute the point at curve abscissa
74
- #
75
- # abstract
76
- #
77
- # must be defined
78
- def point( abscissa, container=nil )
79
- raise NotImplementedError.new("#{self.class.name}#curve is an abstract method.")
80
- end
81
-
82
- # must compute the tangent at curve abscissa
83
- #
84
- # abstract
85
- #
86
- # must be defined
87
- def tangent( abscissa, container=nil )
88
- raise NotImplementedError.new("#{self.class.name}#tangent is an abstract method.")
89
- end
90
-
91
- # must compute the acceleration at curve abscissa
92
- #
93
- # abstract
94
- #
95
- # must be defined
96
- def acc( abscissa, container=nil )
97
- raise NotImplementedError.new("#{self.class.name}#acc is an abstract method.")
98
- end
99
-
100
- # must return the length at abscissa, or total length if abscissa nil
101
- #
102
- # abstract
103
- #
104
- # must be defined
105
- def length(abscissa=nil)
106
- raise NotImplementedError.new("#{self.class.name}#length is an abstract method.")
107
- end
108
-
109
- # default style of a curve, as stroked with stroke width 1% of length
110
- def default_style
111
- return Style[ :stroke, Color.black, :strokewidth, self.length / 100.0 ]
112
- end
113
-
114
- # compute the rotation at curve abscissa, or directly from tangent (for frame computation speed up),
115
- # as angle between tangent0 angle and tangent( abscissa ) (or tangent) angle
116
- def rotation( abscissa, tangent=nil )
117
- if not tangent
118
- tangent = self.tangent( abscissa )
119
- end
120
- return (tangent.angle - self.tangent0_angle)
121
- end
122
-
123
- # must compute the scale at curve abscissa, or directly from tangent (for frame computation speed up)
124
- # as ratio between tangent0 size and tangent( abscissa ) (or tangent) size
125
- def scale( abscissa, tangent=nil )
126
- if not tangent
127
- tangent = self.tangent( abscissa )
128
- end
129
- result = 0.0
130
- if not self.tangent0_length == 0.0
131
- result = (tangent.r / self.tangent0_length)
132
- end
133
- return result
134
- end
135
-
136
- def tangent0
137
- if not @tangent0
138
- @tangent0 = self.tangent( 0.0 )
139
- end
140
- return @tangent0
141
- end
142
-
143
- # TODO : must be cached in vector
144
- def tangent0_angle
145
- if not @tangent0_angle
146
- @tangent0_angle = self.tangent0.angle
147
- end
148
- return @tangent0_angle
149
- end
150
-
151
- # TODO : must be cached in vector
152
- def tangent0_length
153
- if not @tangent0_length
154
- @tangent0_length = self.tangent0.r
155
- end
156
- return @tangent0_length
157
- end
158
-
159
- # compute frame vector at abscissa t, that is [curve.point( t ), curve.tangent( t ) ]
160
- def framev( t )
161
- return [self.point( t ), self.tangent( t ) ]
162
- end
163
-
164
- # compute frame at abscissa t
165
- def frame( t )
166
- point, tangent = self.framev( t )
167
- return Frame[ :center, point, :vector, tangent, :rotation, self.rotation( nil, tangent ), :scale, self.scale( nil, tangent ) ]
168
- end
169
-
170
- # compute normal at abscissa t
171
- #
172
- # do tangent.ortho
173
- def normal( t )
174
- return self.tangent( t ).ortho
175
- end
176
-
177
- # compute normal acceleration at abscissa t
178
- def acc_normal( t )
179
- normal = self.normal( t ).norm
180
- result = self.acc( t ).inner_product( normal )
181
- return result
182
- end
183
-
184
- # compute curvature at abscissa t
185
- def curvature( t )
186
- acc_normal = self.acc_normal( t )
187
- if acc_normal == 0.0
188
- return 0.0
189
- end
190
- return 1.0 / (self.tangent( t ).r / acc_normal )
191
- end
192
-
193
- # shortcut method to map frames from abscissas
194
- def frames (abscissas)
195
- return abscissas.map { |abscissa| self.frame( abscissa ) }
196
- end
197
-
198
- # shortcut method to map points from abscissas
199
- def points (abscissas)
200
- result = abscissas.map { |abscissa| self.point( abscissa ) }
201
- return result
202
- end
203
-
204
- # shortcut method to map tangents from abscissas
205
- def tangents (abscissas)
206
- return abscissas.map { |abscissa| self.tangent( abscissa ) }
207
- end
208
-
209
- # shortcut method, map of normal
210
- def normals( indexes )
211
- return indexes.map {|i| self.normal( i )}
212
- end
213
-
214
- end
215
-
216
-
217
- # Line class
218
- # = Intro
219
- # Used to draw polylines and polygons
220
- # = Attributes
221
- # attribute :points, [V2D[0.0, 0.0], V2D[1.0, 1.0]]
222
- # WARNING : getter "points" is not defined, because is defined as Curve.points( abscissa ) !!!
223
- # = Example
224
- # line = Line[ :points, [V2D::O, V2D::X] ]
225
- class Line < Curve
226
- attribute :points, [V2D[0.0, 0.0], V2D[1.0, 1.0]]
227
-
228
- def initialize (*args) #:nodoc:
229
- super( *args )
230
- self.init_tangents
231
- end
232
-
233
- def init_tangents #:nodoc:
234
- index = 0
235
- @tangents = Array.new
236
- @points.pairs { |p1, p2|
237
- @tangents[ index ] = (p2-p1).norm
238
- index += 1
239
- }
240
- end
241
-
242
- # return the total length of the polyline
243
- def length
244
- if not @length
245
- @length = 0.0
246
- @points.pairs do |p1, p2|
247
- @length += (p1 - p2).r
248
- end
249
- end
250
- return @length
251
- end
252
-
253
- # compute line point at abscissa
254
- # Line[ :points, [V2D::O, V2D::X] ].point( 0.3 ) => V2D[0.0,0.3]
255
- def point (abscissa, container=nil)
256
- container ||= V2D[]
257
- piece1 = abscissa.to_int
258
- if piece1 == @points.size - 1
259
- container.xy = @points[-1]
260
- else
261
- abscissa -= piece1
262
- cpoints = @points.slice( piece1, 2 )
263
- container.xy = [(cpoints[0].x..cpoints[1].x).sample( abscissa ),
264
- (cpoints[0].y..cpoints[1].y).sample( abscissa )]
265
- end
266
- return container
267
- end
268
-
269
- # redefining to discriminate between @points and map.point
270
- def points(arg=nil)
271
- if not arg
272
- return @points
273
- else
274
- super(arg)
275
- end
276
- end
277
-
278
- # compute line tangent at abscissa
279
- def tangent (abscissa, container=nil)
280
- container ||= V2D[]
281
- container.xy = @tangents[abscissa.to_int]
282
- return container
283
- end
284
-
285
- # acc V2D.O
286
- def acc( abscissa, container=nil )
287
- container ||= V2D[]
288
- container.xy = [0.0,0.0]
289
- return container
290
- end
291
-
292
- # compute viewbox of the line
293
- #
294
- # simply call V2D.viewbox on :points
295
- def viewbox
296
- return V2D.viewbox( @points )
297
- end
298
-
299
- # translate a line of v offset, v being a vector
300
- #
301
- # return a new line with every point of :points translated
302
- def translate( v )
303
- return Line[ :points, @points.map {|ext| ext + v } ]
304
- end
305
-
306
- # reverse a line
307
- #
308
- # return a new line with :points reversed
309
- def reverse
310
- return Line[ :points, @points.reverse ]
311
- end
312
-
313
- # return line svg description
314
- def svg
315
- path = "M #{points[0].x} #{points[0].y} "
316
- @points[1..-1].each { |p|
317
- path += "L #{p.x} #{p.y}"
318
- }
319
- return "<path d=\"" + path + "\"/>"
320
- end
321
-
322
- include Samplable
323
- alias apply_sample point
324
- end
325
-
326
- # Circle class
327
- # = Intro
328
- # define a circle curve
329
- # = Attributes
330
- # attribute :center, V2D[0.0,0.0]
331
- # attribute :radius, 1.0
332
- # attribute :initangle, 0.0
333
- # = Example
334
- # c = Circle[ :center, V2D::O, :radius, 1.0 ] # equiv Circle[]
335
- class Circle < Curve
336
- attribute :center, V2D[0.0,0.0]
337
- attribute :radius, 1.0
338
- attribute :initangle, 0.0
339
-
340
- # Circle builder from points diametraly opposed
341
- # Circle.diameter( V2D[-1.0,0.0], V2D[1.0,0.0] ) == Circle[ :center, V2D::O, :radius, 1.0 ]
342
- def Circle.diameter( p1, p2 )
343
- initangle = ( p1 - p2 ).angle
344
- return Circle[ :center, (p1 + p2)/2.0, :radius, (p1 - p2).r/2.0, :initangle, initangle ]
345
- end
346
-
347
- # compute length of the circle
348
- def length
349
- if not @length
350
- @length = 2.0 * Math::PI * self.radius
351
- end
352
- return @length
353
- end
354
-
355
- # shortcut method to retun center.x
356
- def cx
357
- return self.center.x
358
- end
359
-
360
- # shortcut method to retun center.y
361
- def cy
362
- return self.center.y
363
- end
364
-
365
- # viewbox of the circle
366
- def viewbox
367
- return [ self.cx - self.radius,
368
- self.cy - self.radius,
369
- self.cx + self.radius,
370
- self.cy + self.radius ]
371
- end
372
-
373
- # size of the circle
374
- def size
375
- return [ self.radius, self.radius ]
376
- end
377
-
378
- def rotate( angle )
379
- return Circle[:center, self.center, :radius, self.radius, :initangle, self.initangle + angle]
380
- end
381
-
382
- # svg description of the circle
383
- def svg
384
- template = '<circle cx="%cx%" cy="%cy%" r="%r%"/>'
385
- return template.subreplace( {"%cx%" => cx,
386
- "%cy%" => cy,
387
- "%r%" => radius} )
388
- end
389
-
390
- # compute point at abscissa
391
- def point (abscissa, container=nil)
392
- angle = Range::Angle.sample( abscissa ) + @initangle
393
- container ||=V2D[]
394
- container.x = self.cx + self.radius * Math.cos( angle )
395
- container.y = self.cy + self.radius * Math.sin( angle )
396
- return container
397
- end
398
-
399
- # compute tangent at abscissa
400
- def tangent( abscissa, container=nil )
401
- angle = Range::Angle.sample( abscissa ) + @initangle
402
- container ||=V2D[]
403
- container.x = -self.radius * Math.sin( angle )
404
- container.y = self.radius * Math.cos( angle )
405
- return container
406
- end
407
-
408
- # compute acc at abscissa
409
- def acc( abscissa, container=nil )
410
- angle = Range::Angle.sample( abscissa ) + @initangle
411
- container ||=V2D[]
412
- container.x = -self.radius * Math.cos( angle )
413
- container.y = -self.radius * Math.sin( angle )
414
- return container
415
- end
416
-
417
-
418
- include Samplable
419
- alias apply_sample point
420
- end
421
- end
data/lib/spiral.rb DELETED
@@ -1,72 +0,0 @@
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/style.rb DELETED
@@ -1,76 +0,0 @@
1
- #
2
- # See +Style+
3
- #
4
- require 'attributable'
5
- require 'utils'
6
- require 'color'
7
-
8
- module XRVG
9
- #
10
- # Style class
11
- #
12
- # Used to define the way an object has to be rendered.
13
- # For the moment, only the following style attributes are really useful :
14
- # - attribute :fill, "none", [String, Color, Gradient]
15
- # - attribute :stroke, "none", [String, Color, Gradient]
16
- # - attribute :strokewidth, 1.0
17
- #
18
- # For example :
19
- # render.add( Circle[], Style[ :fill, Color.red ] )
20
- # render.add( Circle[], Style[ :stroke, Color.red ] )
21
- class Style
22
- include Attributable
23
- # attribute :opacity, 1.0
24
- attribute :fill, "none", [String, Color, Gradient]
25
- # attribute :fillopacity, 1.0
26
- attribute :stroke, "none", [String, Color, Gradient]
27
- attribute :strokewidth, 1.0
28
- # attribute :strokeopacity, 1.0
29
-
30
- def fillopacity()
31
- if @fill.is_a? Color
32
- return @fill.a
33
- end
34
- return 1.0
35
- end
36
-
37
- def strokeopacity()
38
- if @stroke.is_a? Color
39
- return @stroke.a
40
- end
41
- return 1.0
42
- end
43
-
44
-
45
- def svgfill
46
- if fill.is_a? Color
47
- return fill.svg
48
- elsif fill.is_a? Gradient
49
- return "%fillgradient%"
50
- else
51
- return fill
52
- end
53
- end
54
-
55
- def svgstroke
56
- if stroke.is_a? Color
57
- return stroke.svg
58
- elsif stroke.is_a? Gradient
59
- return "%strokegradient%"
60
- else
61
- return stroke
62
- end
63
- end
64
-
65
- def svgline
66
- template = 'style="opacity:%opacity%;fill:%fill%;fill-opacity:%fillopacity%;stroke:%stroke%;stroke-width:%strokewidth%;stroke-opacity:%strokeopacity%"'
67
-
68
- return template.subreplace( {"%opacity%" => 1.0,
69
- "%fill%" => svgfill,
70
- "%fillopacity%" => fillopacity,
71
- "%stroke%" => svgstroke,
72
- "%strokewidth%" => strokewidth,
73
- "%strokeopacity%" => strokeopacity} )
74
- end
75
- end
76
- end
data/lib/xrvg.rb DELETED
@@ -1,46 +0,0 @@
1
- # This file has to be included if you want to start a XRVG script
2
- #
3
- # Please refer to README for XRVG introduction
4
-
5
- # XRVG version (used in rakefile)
6
- XRVG_VERSION = "0.0.6"
7
-
8
- # XRVG namespace
9
- module XRVG
10
- end
11
-
12
- # Standard Ruby extensions
13
- require 'enumerator'
14
-
15
- # XRVG Infrastructure
16
- require 'trace'
17
-
18
- # XRVG new mixins
19
- require 'samplation'
20
- require 'attributable'
21
- require 'interpolation'
22
- require 'parametriclength'
23
-
24
- # XRVG base class extensions
25
- require 'utils'
26
- require 'geometry2D'
27
-
28
- # XRVG base classes
29
- require 'color'
30
- require 'frame'
31
- require 'shape'
32
- require 'render'
33
- require 'bezier'
34
-
35
- # XRVG extensions
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
-
46
-