xrvg 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. data/CHANGES +8 -0
  2. data/README +1 -1
  3. data/Rakefile +36 -6
  4. data/examples/arciterate1.rb +13 -0
  5. data/examples/arcrecurse1.rb +30 -0
  6. data/examples/arcrecurse2.rb +37 -0
  7. data/examples/circleiterate1.rb +9 -0
  8. data/examples/circleiterate2.rb +11 -0
  9. data/examples/circleiterate3.rb +13 -0
  10. data/examples/circlerecurse1.rb +27 -0
  11. data/examples/circlerecurse2.rb +27 -0
  12. data/examples/circlerecurseall.rb +29 -0
  13. data/examples/euclideangeo.rb +11 -0
  14. data/examples/evolution1.rb +8 -0
  15. data/examples/evolution2.rb +9 -0
  16. data/examples/evolution3.rb +10 -0
  17. data/examples/fuseaugeo.rb +16 -0
  18. data/examples/gradientgeo.rb +21 -0
  19. data/examples/interbeziergeo1.rb +14 -0
  20. data/examples/interbeziergeo2.rb +17 -0
  21. data/examples/interbeziergeo3.rb +17 -0
  22. data/examples/offsetgeo.rb +16 -0
  23. data/lib/bezier.rb +37 -3
  24. data/lib/bezierbuilders.rb +17 -1
  25. data/lib/beziermotifs.rb +11 -4
  26. data/lib/bezierspline.rb +23 -1
  27. data/lib/beziertools.rb +48 -14
  28. data/lib/color.rb +55 -8
  29. data/lib/fitting.rb +2 -2
  30. data/lib/geometry2D.rb +10 -3
  31. data/lib/geovariety.rb +128 -0
  32. data/lib/interbezier.rb +4 -4
  33. data/lib/interpolation.rb +30 -17
  34. data/lib/parametriclength.rb +3 -2
  35. data/lib/render.rb +1 -2
  36. data/lib/samplation.rb +121 -19
  37. data/lib/shape.rb +2 -2
  38. data/lib/spiral.rb +72 -0
  39. data/lib/utils.rb +97 -76
  40. data/lib/xrvg.rb +3 -3
  41. data/test/test_bezier.rb +17 -2
  42. data/test/test_bezierbuilders.rb +1 -1
  43. data/test/test_beziertools.rb +7 -0
  44. data/test/test_color.rb +12 -0
  45. data/test/test_geovariety.rb +105 -0
  46. data/test/test_interpolation.rb +2 -1
  47. data/test/test_render.rb +0 -4
  48. data/test/test_sample.rb +28 -0
  49. data/test/test_spiral.rb +22 -0
  50. data/test/test_utils.rb +65 -40
  51. metadata +26 -2
data/CHANGES CHANGED
@@ -1,5 +1,13 @@
1
1
  = CHANGES
2
2
 
3
+ == 0.0.6 (2008.03.24)
4
+ === Content
5
+ - Add Spiral classes
6
+ - refactor some Float utilitaries into Range class
7
+ - refactor Ondulation bezier builder
8
+ - WARNING: random() filter now always sort its result => Shuffle filter is created. Moreover, .rand method is now only on Random, and not in Samplable interface (due to overloading Array method when using sort_by {rand, which is no good)
9
+
10
+
3
11
  == 0.0.5 (2008.03.22)
4
12
  === Content
5
13
  - Add GeoVariety classes
data/README CHANGED
@@ -1,6 +1,6 @@
1
1
  = XRVG -- X Ruby Vector Graphics
2
2
 
3
- Supporting XRVG version: 0.0.5
3
+ Supporting XRVG version: 0.0.6
4
4
 
5
5
  This package contains XRVG, a Ruby vector graphic programming library.
6
6
 
data/Rakefile CHANGED
@@ -63,7 +63,7 @@ RDOC_FILES = FileList["README", "CHANGES"]
63
63
 
64
64
  # Ruby library code.
65
65
  LIB_DIR = "lib"
66
- PRE_LIB_FILES = FileList["trace.rb", "samplation.rb", "interpolation.rb", "parametriclength.rb", "utils.rb", "geometry2D.rb", "color.rb", "frame.rb", "shape.rb", "render.rb", "shape.rb", "style.rb", "bezier.rb", "bezierspline.rb", "fitting.rb", "bezierbuilders.rb", "beziermotifs.rb", "beziertools.rb", "interbezier.rb", "geovariety.rb", "xrvg.rb"]
66
+ PRE_LIB_FILES = FileList["trace.rb", "samplation.rb", "interpolation.rb", "parametriclength.rb", "utils.rb", "geometry2D.rb", "color.rb", "frame.rb", "shape.rb", "render.rb", "shape.rb", "style.rb", "bezier.rb", "bezierspline.rb", "fitting.rb", "bezierbuilders.rb", "beziermotifs.rb", "beziertools.rb", "interbezier.rb", "geovariety.rb", "spiral.rb", "xrvg.rb"]
67
67
  LIB_FILES = FileList["#{LIB_DIR}/*.rb"]
68
68
 
69
69
  # Example code.
@@ -89,9 +89,9 @@ DIST_FILES.include(BIN_FILES)
89
89
  # Don't package files which are autogenerated by RDocTask
90
90
  DIST_FILES.exclude(/^(\.\/)?#{RDOC_HTML_DIR}(\/|$)/)
91
91
  # Include extension source files.
92
- DIST_FILES.include(EXT_DIST_FILES)
92
+ # DIST_FILES.include(EXT_DIST_FILES)
93
93
  # Don't package temporary files, perhaps created by tests.
94
- DIST_FILES.exclude("**/temp_*", "**/*.tmp", "**/*.svg" )
94
+ # DIST_FILES.exclude("**/temp_*", "**/*.tmp", "**/*.svg", "*.svg" )
95
95
  # Don't get into recursion...
96
96
  DIST_FILES.exclude(/^(\.\/)?pkg(\/|$)/)
97
97
  #---
@@ -184,12 +184,28 @@ task "upload-website" do
184
184
  sh "winscp.exe /console /script=winscp_script.txt"
185
185
  end
186
186
 
187
+ #---
188
+ desc "Upload blog to RubyForge with WinSCP"
189
+ task "upload-blog" do
190
+ sh "winscp.exe /console /script=winscp_script_blog.txt"
191
+ end
192
+
193
+
194
+ #---
195
+ desc "Regenerate blog"
196
+ task "gen-blog" do
197
+ # Rake::Task["clobber"].invoke
198
+ Rake::Task["muse"].invoke
199
+ # Rake::Task["examples"].invoke; # must be done with emacs
200
+ Rake::Task["finish"].invoke
201
+ end
202
+
187
203
  #---
188
204
  desc "Regenerate website"
189
205
  task "gen-website" do
190
206
  Rake::Task["clobber"].invoke
191
- Rake::Task["muse"].invoke
192
- Rake::Task["examples"].invoke
207
+ # Rake::Task["muse"].invoke
208
+ # Rake::Task["examples"].invoke
193
209
  Rake::Task["rdoc"].invoke
194
210
  Rake::Task["finish"].invoke
195
211
  end
@@ -201,9 +217,22 @@ task "publish-website" do
201
217
  # sh "scp -r #{WEBSITE_DIR}/* " +
202
218
  # "#{RUBYFORGE_USER}@rubyforge.org:#{rubyforge_path}",
203
219
  # :verbose => true
204
- Rake::Task["gen-website"].invoke
220
+ # Commented because must be triggered explictely as very long: Rake::Task["gen-website"].invoke
205
221
  Rake::Task["upload-website"].invoke
206
222
  end
223
+
224
+ #---
225
+ desc "Regenerate blog and upload it to RubyForge"
226
+ task "publish-blog" do
227
+ # rubyforge_path = "/var/www/gforge-projects/#{UNIX_NAME}/"
228
+ # sh "scp -r #{WEBSITE_DIR}/* " +
229
+ # "#{RUBYFORGE_USER}@rubyforge.org:#{rubyforge_path}",
230
+ # :verbose => true
231
+ Rake::Task["gen-blog"].invoke
232
+ Rake::Task["upload-blog"].invoke
233
+ end
234
+
235
+
207
236
  #---
208
237
  task "rubyforge-setup" do
209
238
  unless File.exist?(File.join(ENV["HOME"], ".rubyforge"))
@@ -280,6 +309,7 @@ task "examples" => ["muse"] do
280
309
  mkdir "#{WEBSITE_DIR}/images"
281
310
  require 'www/example_list'
282
311
  example_list.each do |fn|
312
+ puts "generate #{fn} ..."
283
313
  source = fn
284
314
  svg = String.new(fn)
285
315
  svg["\.rb"] = ".svg"
@@ -0,0 +1,13 @@
1
+ require 'xrvg'
2
+ include XRVG
3
+
4
+ render = SVGRender[:imagesize, "3cm" ]
5
+ style = Style[ :stroke, Color.blue, :strokewidth, 0.01 ]
6
+ arc = ArcBezier[ :support, [V2D::O, V2D::X] ]
7
+ samples = [0.1,0.3,0.4,0.6,0.7,0.9]
8
+ subarcs = arc.samples( samples ).foreach(2).map do |points|
9
+ ArcBezier[ :support, points ]
10
+ end
11
+ render.add( arc, style )
12
+ subarcs.each {|arc| render.add( arc, style ) }
13
+ render.end
@@ -0,0 +1,30 @@
1
+ require 'xrvg'
2
+ include XRVG
3
+
4
+ def subarcs( arc, samples )
5
+ return arc.samples( samples ).foreach(2).map do |points|
6
+ ArcBezier[:support, points ]
7
+ end
8
+ end
9
+
10
+ def arcrecurse( arcs, niter, samples )
11
+ if niter == 0
12
+ return arcs
13
+ else
14
+ subarcs = []
15
+ arcs.each do |arc|
16
+ subarcs += subarcs( arc, samples )
17
+ end
18
+ return arcrecurse( subarcs, niter-1, samples )
19
+ end
20
+ end
21
+
22
+ render = SVGRender[:imagesize, "3cm" ]
23
+ style = Style[ :stroke, Color.blue, :strokewidth, 0.01 ]
24
+ samples = [0.1,0.3,0.4,0.6,0.7,0.9]
25
+ roots = [ArcBezier[ :support, [V2D::O, V2D::X]]]
26
+ arcrecurse( roots, 4, samples ).each do |arc|
27
+ render.add( arc, style )
28
+ end
29
+ render.end
30
+
@@ -0,0 +1,37 @@
1
+ require 'xrvg'
2
+ include XRVG
3
+
4
+ def subarcs( arc, samples )
5
+ return arc.samples( samples ).foreach(2).map do |points|
6
+ ArcBezier[:support, points ]
7
+ end
8
+ end
9
+
10
+ def arcrecurse( arcs, niter, samples )
11
+ if niter <= 0
12
+ return arcs
13
+ else
14
+ subarcs = []
15
+ arcs.each do |arc|
16
+ subarcs += subarcs( arc, samples )
17
+ end
18
+ return arcrecurse( subarcs, niter-1, samples )
19
+ end
20
+ end
21
+
22
+ render = SVGRender[:imagesize, "3cm" ]
23
+ style = Style[ :stroke, Color.blue, :strokewidth, 0.01 ]
24
+ samples = [0.1,0.3,0.4,0.6,0.7,0.9]
25
+ roots = [ArcBezier[ :support, [V2D::O, V2D::X]]]
26
+ palette = Palette[ :colorlist, [ 0.0, Color.black,
27
+ 1.0, Color.blue]]
28
+ niter = 6
29
+ [(0.0..1.0),(0.01..0.001),palette].samples( niter ) do |time,width,color|
30
+ time = (niter * time).to_i
31
+ style.stroke = color
32
+ style.strokewidth = width
33
+ arcrecurse( roots, time, samples ).each do |arc|
34
+ render.add( arc, style )
35
+ end
36
+ end
37
+ render.end
@@ -0,0 +1,9 @@
1
+ require 'xrvg'
2
+ include XRVG
3
+
4
+ render = SVGRender[:imagesize, "3cm" ]
5
+ style = Style[ :fill, Color.blue ]
6
+ Circle[].samples( 6 ) do |point|
7
+ render.add( Circle[:center, point, :radius, 0.333 ], style)
8
+ end
9
+ render.end
@@ -0,0 +1,11 @@
1
+ require 'xrvg'
2
+ include XRVG
3
+
4
+ render = SVGRender[:imagesize, "3cm" ]
5
+ style = Style[ :fill, Color.blue ]
6
+ Circle[].samples( 6 ) do |point|
7
+ Circle[:center, point, :radius, 0.3333 ].samples( 6 ) do |point|
8
+ render.add( Circle[:center, point, :radius, 0.1111 ], style )
9
+ end
10
+ end
11
+ render.end
@@ -0,0 +1,13 @@
1
+ require 'xrvg'
2
+ include XRVG
3
+
4
+ render = SVGRender[:imagesize, "3cm" ]
5
+ style = Style[ :fill, Color.blue ]
6
+ Circle[].samples( 6 ) do |point|
7
+ Circle[:center, point, :radius, 0.3333 ].samples( 6 ) do |point|
8
+ Circle[:center, point, :radius, 0.1111 ].samples( 6 ) do |point|
9
+ render.add( Circle[:center, point, :radius, 0.037 ], style )
10
+ end
11
+ end
12
+ end
13
+ render.end
@@ -0,0 +1,27 @@
1
+ require 'xrvg'
2
+ include XRVG
3
+
4
+ def subcircles( circle, nsamples, radiusfactor )
5
+ return circle.samples( nsamples )[1..-1].map do |point|
6
+ Circle[:center, point, :radius, circle.radius * radiusfactor ]
7
+ end
8
+ end
9
+
10
+ def circlerecurse( circles, niter, nsamples, radiusfactor )
11
+ if niter == 0
12
+ return circles
13
+ else
14
+ subcircles = []
15
+ circles.each do |circle|
16
+ subcircles += subcircles( circle, nsamples, radiusfactor )
17
+ end
18
+ return circlerecurse( subcircles, niter-1, nsamples, radiusfactor )
19
+ end
20
+ end
21
+
22
+ render = SVGRender[:imagesize, "3cm" ]
23
+ style = Style[ :fill, Color.blue ]
24
+ circlerecurse( [Circle[]], 4, 6, 1.0/3.0 ).each do |circle|
25
+ render.add( circle, style )
26
+ end
27
+ render.end
@@ -0,0 +1,27 @@
1
+ require 'xrvg'
2
+ include XRVG
3
+
4
+ def subcircles( circle, nsamples, radiusfactor )
5
+ return circle.samples( nsamples )[1..-1].map do |point|
6
+ Circle[:center, point, :radius, circle.radius * radiusfactor ]
7
+ end
8
+ end
9
+
10
+ def circlerecurse( circles, niter, nsamples, radiusfactor )
11
+ if niter == 0
12
+ return circles
13
+ else
14
+ subcircles = []
15
+ circles.each do |circle|
16
+ subcircles += subcircles( circle, nsamples, radiusfactor )
17
+ end
18
+ return circlerecurse( subcircles, niter-1, nsamples, radiusfactor )
19
+ end
20
+ end
21
+
22
+ render = SVGRender[:imagesize, "3cm" ]
23
+ style = Style[ :fill, Color.blue ]
24
+ circlerecurse( [Circle[]], 5, 6, 1.0/3.0 ).each do |circle|
25
+ render.add( circle, style )
26
+ end
27
+ render.end
@@ -0,0 +1,29 @@
1
+ require 'xrvg'
2
+ include XRVG
3
+
4
+ def subcircles( circle, nsamples, radiusfactor )
5
+ return circle.samples( nsamples )[1..-1].map do |point|
6
+ Circle[:center, point, :radius, circle.radius * radiusfactor ]
7
+ end
8
+ end
9
+
10
+ def circlerecurse( circles, niter, nsamples, radiusfactor )
11
+ if niter == 0
12
+ return circles
13
+ else
14
+ subcircles = []
15
+ circles.each do |circle|
16
+ subcircles += subcircles( circle, nsamples, radiusfactor )
17
+ end
18
+ return circlerecurse( subcircles, niter-1, nsamples, radiusfactor )
19
+ end
20
+ end
21
+
22
+ render = SVGRender[:imagesize, "3cm" ]
23
+ style = Style[ :fill, Color.blue( 0.2 ) ]
24
+ 5.times do |time|
25
+ circlerecurse( [Circle[]], time, 6, 1.0/3.0 ).each do |circle|
26
+ render.add( circle, style )
27
+ end
28
+ end
29
+ render.end
@@ -0,0 +1,11 @@
1
+ require 'xrvg'
2
+ include XRVG
3
+
4
+ render = SVGRender[:imagesize,"3cm"]
5
+ style = Style[ :stroke, Color.blue( 0.3 ), :strokewidth, 0.01 ]
6
+ 100.times do
7
+ xs = (0.0..1.0).ssort().rand( 2 )
8
+ y = (0.0..1.0).rand
9
+ render.add( Line[ :points, xs.map {|x| V2D[x, y]} ], style )
10
+ end
11
+ render.end
@@ -0,0 +1,8 @@
1
+ require 'xrvg'
2
+ include XRVG
3
+
4
+ render = SVGRender[:imagesize, "3cm" ]
5
+ line = LinearBezier.buildwithangle( Range.Angle.sample( 0.95 ) )
6
+ style = Style[ :stroke, Color.blue, :strokewidth, 0.01 ]
7
+ render.add( line, style )
8
+ render.end
@@ -0,0 +1,9 @@
1
+ require 'xrvg'
2
+ include XRVG
3
+
4
+ render = SVGRender[:imagesize, "3cm" ]
5
+ line = LinearBezier.buildwithangle( Range.Angle.sample( 0.45 ) )
6
+ line = ArcBezier[ :support, [line.pointlist[0], line.pointlist[-1]], :height, 0.7 ]
7
+ style = Style[ :stroke, Color.blue, :strokewidth, 0.01 ]
8
+ render.add( line, style )
9
+ render.end
@@ -0,0 +1,10 @@
1
+ require 'xrvg'
2
+ include XRVG
3
+
4
+ render = SVGRender[:imagesize, "3cm" ]
5
+ line = LinearBezier.buildwithangle( Range.Angle.sample( 0.45 ) )
6
+ line = ArcBezier[ :support, [line.pointlist[0], line.pointlist[-1]], :height, 0.7 ]
7
+ pics = line.reverse.geofull(1.2).samples( 20 ).foreach(2).map {|points| PicBezier[:support, points, :height, -3.0]}
8
+ style = Style[ :stroke, Color.blue, :strokewidth, 0.01 ]
9
+ pics.each {|pic| render.add( pic, style )}
10
+ render.end
@@ -0,0 +1,16 @@
1
+ require 'xrvg'
2
+ include XRVG
3
+
4
+ render = SVGRender[:imagesize,"3cm"]
5
+ style = Style[ :stroke, Color.blue( 0.3 ), :strokewidth, 0.01 ]
6
+ support = LinearBezier[ :support, [V2D::O, V2D::X] ]
7
+ support = Ondulation[ :support, support, :freq, 2, :ampl, 0.5 ]
8
+ fuseauvariety = FuseauVariety[ :support, support, :ampl, 0.2 ]
9
+
10
+ 100.times do
11
+ xs = (0.0..1.0).ssort().rand( 2 )
12
+ y = (0.0..1.0).rand
13
+ render.add( fuseauvariety.line( xs[0], xs[1], y), style )
14
+ end
15
+ render.end
16
+
@@ -0,0 +1,21 @@
1
+ require 'xrvg'
2
+ include XRVG
3
+
4
+ render = SVGRender[:imagesize,"3cm"]
5
+
6
+ line = LinearBezier[ :support, [V2D::O, V2D::X]]
7
+ support = line.translate( -V2D::Y )
8
+ ondulation = Ondulation[ :support, support, :freq, 5, :ampl, 0.5 ]
9
+
10
+ gbezier = GradientBezier[ :bezierlist, [0.0, line, 1.0, ondulation]]
11
+
12
+ palette = Palette[ :colorlist, [ 0.0, Color.black,
13
+ 0.5, Color.blue,
14
+ 1.0, Color.white]]
15
+ style = Style.new( :strokewidth, 0.01 )
16
+ [gbezier, palette].samples( 10 ) do |bezier, color|
17
+ style.fill = color
18
+ style.stroke = color
19
+ render.add( bezier, style )
20
+ end
21
+ render.end
@@ -0,0 +1,14 @@
1
+ require 'xrvg'
2
+ include XRVG
3
+
4
+ render = SVGRender[:imagesize,"3cm"]
5
+ style = Style[ :stroke, Color.blue( 0.3 ), :strokewidth, 0.01 ]
6
+ support1 = LinearBezier[ :support, [V2D::O, V2D::X] ]
7
+ support2 = support1.translate( V2D::Y )
8
+ interbezier = InterBezier[ :bezierlist, [0.0, support1, 1.0, support2 ] ]
9
+
10
+ 100.times do
11
+ xs = (0.0..1.0).ssort().rand( 2 )
12
+ render.add( interbezier.line( xs[0], xs[1], (0.0..1.0).rand ), style )
13
+ end
14
+ render.end
@@ -0,0 +1,17 @@
1
+ require 'xrvg'
2
+ include XRVG
3
+
4
+ render = SVGRender[:imagesize,"3cm"]
5
+ style = Style[ :stroke, Color.blue( 0.3 ), :strokewidth, 0.01 ]
6
+ support = LinearBezier[ :support, [V2D::O, V2D::X] ]
7
+ support = support.translate( V2D::Y * 0.2 )
8
+ support1 = Ondulation[ :support, support, :freq, 2, :ampl, 0.5 ]
9
+ support = support.translate( -V2D::Y * 0.4 )
10
+ support2 = Ondulation[ :support, support, :freq, 2, :ampl, 0.5 ]
11
+ interbezier = InterBezier[ :bezierlist, [0.0, support1, 1.0, support2 ] ]
12
+
13
+ 100.times do
14
+ xs = (0.0..1.0).ssort().rand( 2 )
15
+ render.add( interbezier.line( xs[0], xs[1], (0.0..1.0).rand ), style )
16
+ end
17
+ render.end
@@ -0,0 +1,17 @@
1
+ require 'xrvg'
2
+ include XRVG
3
+
4
+ render = SVGRender[:imagesize,"3cm"]
5
+ style = Style[ :stroke, Color.blue( 0.3 ), :strokewidth, 0.01 ]
6
+ support = LinearBezier[ :support, [V2D::O, V2D::X] ]
7
+ support = Ondulation[ :support, support, :freq, 2, :ampl, 0.3 ]
8
+ support1 = Offset[ :support, support, :ampl, 0.2 ]
9
+ support2 = Offset[ :support, support, :ampl, -0.2 ]
10
+
11
+ interbezier = InterBezier[ :bezierlist, [0.0, support1, 1.0, support2 ] ]
12
+
13
+ 100.times do
14
+ xs = (0.0..1.0).ssort().rand( 2 )
15
+ render.add( interbezier.line( xs[0], xs[1], (0.0..1.0).rand ), style )
16
+ end
17
+ render.end
@@ -0,0 +1,16 @@
1
+ require 'xrvg'
2
+ include XRVG
3
+
4
+ render = SVGRender[:imagesize,"3cm"]
5
+ style = Style[ :stroke, Color.blue( 0.3 ), :strokewidth, 0.01 ]
6
+ support = LinearBezier[ :support, [V2D::O, V2D::X] ]
7
+ support = Ondulation[ :support, support, :freq, 2, :ampl, 0.5 ]
8
+ offsetvariety = OffsetVariety[ :support, support, :ampl, 0.2 ]
9
+
10
+ 100.times do
11
+ xs = (0.0..1.0).ssort().rand( 2 )
12
+ y = (0.0..1.0).rand
13
+ render.add( offsetvariety.line( xs[0], xs[1], y), style )
14
+ end
15
+ render.end
16
+
data/lib/bezier.rb CHANGED
@@ -288,8 +288,25 @@ class Bezier < Curve
288
288
  # compute the sub curve between abscissa t1 and t2
289
289
  #
290
290
  # may result in a multi-pieces Bezier
291
+ #
292
+ # Note: special modulo effect to deal with closed bezier curve
293
+ #
294
+ # TODO: improve code (bas design)
291
295
  def subbezier( t1, t2)
292
- return Bezier.new( :pieces, self.subpieces( t1, t2 ) )
296
+ # return Bezier.new( :pieces, self.subpieces( t1, t2 ) )
297
+ ranges = (0.0..1.0).modulos( (t1..t2) )
298
+ # Trace("Bezier::subbezier t1 #{t1} t2 #{t2} ranges #{ranges.inspect}")
299
+ pieces = []
300
+ ranges.each do |range|
301
+ range = range.sort
302
+ pieces += self.subpieces( range.begin, range.end )
303
+ end
304
+
305
+ bezier = Bezier.new( :pieces, pieces )
306
+ if t1 > t2
307
+ bezier = bezier.reverse
308
+ end
309
+ return bezier
293
310
  end
294
311
 
295
312
  # -------------------------------------------------------------
@@ -311,7 +328,22 @@ class Bezier < Curve
311
328
  # translate the Bezier curve, by translating its points
312
329
  def translate( v )
313
330
  return Bezier.new( :pieces, @pieces.map { |piece| piece.translate( v ) } )
314
- end
331
+ end
332
+
333
+ # rotate the Bezier curve, by rotating its points
334
+ def rotate( angle, center=V2D::O )
335
+ return Bezier.new( :pieces, @pieces.map { |piece| piece.rotate( angle, center ) } )
336
+ end
337
+
338
+ # central symetry
339
+ def sym( center )
340
+ return Bezier.new( :pieces, @pieces.map { |piece| piece.sym( center ) } )
341
+ end
342
+
343
+ # axis symetry
344
+ def axesym( point, v )
345
+ return Bezier.new( :pieces, @pieces.map { |piece| piece.axesym( point, v ) } )
346
+ end
315
347
 
316
348
  # -------------------------------------------------------------
317
349
  # similar (transform is used for samplation)
@@ -424,7 +456,7 @@ class Bezier < Curve
424
456
  lmin = 0.0
425
457
  @lengthranges = []
426
458
  lengths.each do |llength|
427
- Trace("lmin #{lmin} llength #{llength}")
459
+ # Trace("lmin #{lmin} llength #{llength}")
428
460
  @lengthranges << (lmin..llength)
429
461
  lmin = llength
430
462
  end
@@ -500,3 +532,5 @@ class Bezier < Curve
500
532
  # TODO : add generic bezier builder from points : must be adaptative !! (use Fitting)
501
533
  end
502
534
  end
535
+
536
+
@@ -186,7 +186,23 @@ end
186
186
  class Circle
187
187
  # return approximating bezier curve
188
188
  def bezier
189
- return FitBezierBuilder[ :points, self.samples( 20 ) ]
189
+ # following computation is too expensive
190
+ # return FitBezierBuilder[ :points, self.samples( 20 ) ]
191
+
192
+ # based on http://www.whizkidtech.redprince.net/bezier/circle/
193
+ kappa = 0.5522847498
194
+
195
+ beziers = []
196
+ self.frames( (0.0..1.0).samples(5) ).pairs do |f1,f2|
197
+ beziers << Bezier.vector( f1.center, f1.vector.norm * kappa * self.radius, f2.center, f2.vector.norm * kappa * (-self.radius) )
198
+ end
199
+
200
+ result = beziers[0]
201
+ beziers[1..-1].each do |b|
202
+ result = result + b
203
+ end
204
+
205
+ return result
190
206
  end
191
207
  end
192
208
 
data/lib/beziermotifs.rb CHANGED
@@ -17,6 +17,17 @@ module XRVG
17
17
  class BezierMotif < BezierBuilder
18
18
  include Attributable
19
19
  attribute :support
20
+
21
+ def BezierMotif.build( *args )
22
+ builder = self.new( *args )
23
+ result = []
24
+ builder.support.pairs do |p1,p2|
25
+ builder.support = [p1,p2]
26
+ result << Bezier.multi( builder.compute )
27
+ end
28
+ return result.sum
29
+ end
30
+
20
31
  end
21
32
 
22
33
 
@@ -108,7 +119,3 @@ class LinearBezier < BezierMotif
108
119
  end
109
120
 
110
121
  end # end XRVG
111
-
112
-
113
-
114
-
data/lib/bezierspline.rb CHANGED
@@ -181,12 +181,34 @@ class BezierSpline #:nodoc:
181
181
  end
182
182
 
183
183
  # simple translation operation : translate every point of the piece
184
- # return a new Bezier
184
+ # return a new BezierSpline
185
185
  def translate( v )
186
186
  newpoints = self.pointlist.map {|point| point + v}
187
187
  return BezierSpline[ :raw, *newpoints ]
188
188
  end
189
189
 
190
+ # simple rotation operation : rotate every point of the piece
191
+ # return a new BezierSpline
192
+ def rotate( angle, center )
193
+ newpoints = self.pointlist.map {|point| center + (point-center).rotate( angle )}
194
+ return BezierSpline[ :raw, *newpoints ]
195
+ end
196
+
197
+ # simple sym operation : sym every point of the piece
198
+ # return a new BezierSpline
199
+ def sym( center )
200
+ newpoints = self.pointlist.map {|point| center.sym( point )}
201
+ return BezierSpline[ :raw, *newpoints ]
202
+ end
203
+
204
+
205
+ # simple axe sym operation : sym every point of the piece
206
+ # return a new BezierSpline
207
+ def axesym( origin, v )
208
+ newpoints = self.pointlist.map {|point| point.axesym( origin, v )}
209
+ return BezierSpline[ :raw, *newpoints ]
210
+ end
211
+
190
212
  def gdebug(render)
191
213
  p1, pc1, pc2, p2 = self.pointlist()
192
214
  v1 = pc1 - p1