xrvg 0.0.5 → 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +8 -0
- data/README +1 -1
- data/Rakefile +36 -6
- data/examples/arciterate1.rb +13 -0
- data/examples/arcrecurse1.rb +30 -0
- data/examples/arcrecurse2.rb +37 -0
- data/examples/circleiterate1.rb +9 -0
- data/examples/circleiterate2.rb +11 -0
- data/examples/circleiterate3.rb +13 -0
- data/examples/circlerecurse1.rb +27 -0
- data/examples/circlerecurse2.rb +27 -0
- data/examples/circlerecurseall.rb +29 -0
- data/examples/euclideangeo.rb +11 -0
- data/examples/evolution1.rb +8 -0
- data/examples/evolution2.rb +9 -0
- data/examples/evolution3.rb +10 -0
- data/examples/fuseaugeo.rb +16 -0
- data/examples/gradientgeo.rb +21 -0
- data/examples/interbeziergeo1.rb +14 -0
- data/examples/interbeziergeo2.rb +17 -0
- data/examples/interbeziergeo3.rb +17 -0
- data/examples/offsetgeo.rb +16 -0
- data/lib/bezier.rb +37 -3
- data/lib/bezierbuilders.rb +17 -1
- data/lib/beziermotifs.rb +11 -4
- data/lib/bezierspline.rb +23 -1
- data/lib/beziertools.rb +48 -14
- data/lib/color.rb +55 -8
- data/lib/fitting.rb +2 -2
- data/lib/geometry2D.rb +10 -3
- data/lib/geovariety.rb +128 -0
- data/lib/interbezier.rb +4 -4
- data/lib/interpolation.rb +30 -17
- data/lib/parametriclength.rb +3 -2
- data/lib/render.rb +1 -2
- data/lib/samplation.rb +121 -19
- data/lib/shape.rb +2 -2
- data/lib/spiral.rb +72 -0
- data/lib/utils.rb +97 -76
- data/lib/xrvg.rb +3 -3
- data/test/test_bezier.rb +17 -2
- data/test/test_bezierbuilders.rb +1 -1
- data/test/test_beziertools.rb +7 -0
- data/test/test_color.rb +12 -0
- data/test/test_geovariety.rb +105 -0
- data/test/test_interpolation.rb +2 -1
- data/test/test_render.rb +0 -4
- data/test/test_sample.rb +28 -0
- data/test/test_spiral.rb +22 -0
- data/test/test_utils.rb +65 -40
- 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
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,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,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
|
+
|
data/lib/bezierbuilders.rb
CHANGED
@@ -186,7 +186,23 @@ end
|
|
186
186
|
class Circle
|
187
187
|
# return approximating bezier curve
|
188
188
|
def bezier
|
189
|
-
|
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
|
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
|