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