xrvg 0.0.5 → 0.0.6

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.
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