xrvg 0.0.1
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/LICENCE +21 -0
- data/README +88 -0
- data/Rakefile +263 -0
- data/examples/foreach.rb +9 -0
- data/examples/hellocrown.rb +7 -0
- data/examples/hellocrown2.rb +7 -0
- data/examples/hellocrownrecurse.rb +9 -0
- data/examples/helloworld.rb +5 -0
- data/examples/helloworldcompact.rb +5 -0
- data/examples/helloworldexpanded.rb +5 -0
- data/examples/palette_circle.rb +10 -0
- data/examples/sample.rb +10 -0
- data/examples/uplets.rb +9 -0
- data/lib/assertion.rb +14 -0
- data/lib/attributable.rb +152 -0
- data/lib/color.rb +295 -0
- data/lib/frame.rb +32 -0
- data/lib/geometry2D.rb +207 -0
- data/lib/interpolation.rb +59 -0
- data/lib/render.rb +269 -0
- data/lib/samplation.rb +416 -0
- data/lib/shape.rb +338 -0
- data/lib/style.rb +74 -0
- data/lib/trace.rb +28 -0
- data/lib/utils.rb +404 -0
- data/lib/xrvg.rb +37 -0
- data/test/test_attributable.rb +24 -0
- data/test/test_color.rb +79 -0
- data/test/test_frame.rb +12 -0
- data/test/test_geometry2D.rb +76 -0
- data/test/test_render.rb +18 -0
- data/test/test_style.rb +16 -0
- data/test/test_utils.rb +207 -0
- metadata +80 -0
data/LICENCE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
Copyright (c) 2008 Julien L�onard
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
21
|
+
|
data/README
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
= XRVG -- X Ruby Vector Graphics
|
2
|
+
|
3
|
+
Supporting XRVG version: 0.0.1
|
4
|
+
|
5
|
+
This package contains XRVG, a Ruby vector graphic programming library.
|
6
|
+
|
7
|
+
== Download
|
8
|
+
|
9
|
+
The latest version of XRVG can be found at
|
10
|
+
|
11
|
+
* http://rubyforge.org/projects/xrvg/
|
12
|
+
|
13
|
+
== Installation
|
14
|
+
|
15
|
+
=== GEM Installation
|
16
|
+
|
17
|
+
Download and install XRVG with the following.
|
18
|
+
|
19
|
+
gem install xrvg
|
20
|
+
|
21
|
+
=== Running the XRVG Test Suite
|
22
|
+
|
23
|
+
XRVG comes with a Rakefile. To launch XRVG tests, simply go into XRVG install directory, and executes
|
24
|
+
rake test
|
25
|
+
|
26
|
+
== Online Resources
|
27
|
+
|
28
|
+
=== XRVG Reference
|
29
|
+
|
30
|
+
* XRVG API Documentation http://xrvg.rubyforge.org/rdoc/index.html
|
31
|
+
|
32
|
+
=== Tutorials
|
33
|
+
|
34
|
+
* http://xrvg.rubyforge.org/XRVGTutorials.html
|
35
|
+
|
36
|
+
=== Road Map
|
37
|
+
|
38
|
+
TO BE DEFINED
|
39
|
+
|
40
|
+
== Simple Example
|
41
|
+
|
42
|
+
To be put in a .rb file
|
43
|
+
|
44
|
+
require 'xrvg'
|
45
|
+
|
46
|
+
render = SVGRender[ :filename, "test.svg" ]
|
47
|
+
render.add( Circle[] )
|
48
|
+
render.end
|
49
|
+
|
50
|
+
== License
|
51
|
+
|
52
|
+
XRVG is available under an MIT-style license.
|
53
|
+
|
54
|
+
:include: LICENCE
|
55
|
+
|
56
|
+
== Support
|
57
|
+
|
58
|
+
The XRVG homepage is http://xrvg.rubyforge.org. You can find the XRVG
|
59
|
+
RubyForge page at http://rubyforge.org/projects/xrvg.
|
60
|
+
|
61
|
+
Feel free to submit commits or feature requests. If you send a patch,
|
62
|
+
remember to update the corresponding unit tests. In fact, I prefer
|
63
|
+
new feature to be submitted in the form of new unit tests.
|
64
|
+
|
65
|
+
For other information, feel free to ask on the ruby-talk mailing list
|
66
|
+
(which is mirrored to comp.lang.ruby) or contact
|
67
|
+
mailto:jblondinet@nospam@yahoo.com.
|
68
|
+
|
69
|
+
|
70
|
+
= Other stuff
|
71
|
+
|
72
|
+
== Credits
|
73
|
+
|
74
|
+
Thanks for Rake project, whose README file has been adapted to do this one.
|
75
|
+
|
76
|
+
== Summary
|
77
|
+
|
78
|
+
Author:: Julien L�onard <jblondinet@nospam@yahoo.com>
|
79
|
+
Requires:: Ruby 1.8.0 or later (but not compatible with 1.9.0)
|
80
|
+
License:: Copyright 2008 by Julien L�onard.
|
81
|
+
Released under an MIT-style license.
|
82
|
+
|
83
|
+
== Warranty
|
84
|
+
|
85
|
+
This software is provided "as is" and without any express or
|
86
|
+
implied warranties, including, without limitation, the implied
|
87
|
+
warranties of merchantibility and fitness for a particular
|
88
|
+
purpose.
|
data/Rakefile
ADDED
@@ -0,0 +1,263 @@
|
|
1
|
+
# Rakefile
|
2
|
+
require "rake/testtask"
|
3
|
+
require "rake/clean"
|
4
|
+
require "rake/rdoctask"
|
5
|
+
require "rake/gempackagetask"
|
6
|
+
#---
|
7
|
+
# The name of your project
|
8
|
+
PROJECT = "XRVG"
|
9
|
+
|
10
|
+
# Your name, used in packaging.
|
11
|
+
MY_NAME = "Julien L�onard"
|
12
|
+
|
13
|
+
# Your email address, used in packaging.
|
14
|
+
MY_EMAIL = "jblondinet@nospam@yahoo.com"
|
15
|
+
|
16
|
+
# Short summary of your project, used in packaging.
|
17
|
+
PROJECT_SUMMARY = "Ruby vector graphics library"
|
18
|
+
|
19
|
+
# The project's package name (as opposed to its display name). Used for
|
20
|
+
# RubyForge connectivity and packaging.
|
21
|
+
UNIX_NAME = "xrvg"
|
22
|
+
|
23
|
+
# Your RubyForge user name.
|
24
|
+
RUBYFORGE_USER = ENV["RUBYFORGE_USER"] || "jblondinet"
|
25
|
+
|
26
|
+
# Directory on RubyForge where your website's files should be uploaded.
|
27
|
+
WEBSITE_DIR = "www"
|
28
|
+
|
29
|
+
# Output directory for the rdoc html files.
|
30
|
+
# If you don't have a custom homepage, and want to use the RDoc
|
31
|
+
# index.html as homepage, just set it to WEBSITE_DIR.
|
32
|
+
RDOC_HTML_DIR = "#{WEBSITE_DIR}/rdoc"
|
33
|
+
#---
|
34
|
+
# Variable settings for extension support.
|
35
|
+
EXT_DIR = "ext"
|
36
|
+
HAVE_EXT = File.directory?(EXT_DIR)
|
37
|
+
EXTCONF_FILES = FileList["#{EXT_DIR}/**/extconf.rb"]
|
38
|
+
EXT_SOURCES = FileList["#{EXT_DIR}/**/*.{c,h}"]
|
39
|
+
# Eventually add other files from EXT_DIR, like "MANIFEST"
|
40
|
+
EXT_DIST_FILES = EXT_SOURCES + EXTCONF_FILES
|
41
|
+
#---
|
42
|
+
REQUIRE_PATHS = ["lib"]
|
43
|
+
REQUIRE_PATHS << EXT_DIR if HAVE_EXT
|
44
|
+
$LOAD_PATH.concat(REQUIRE_PATHS)
|
45
|
+
# This library file defines the RAKEVERSION constant.
|
46
|
+
require "#{UNIX_NAME}"
|
47
|
+
PROJECT_VERSION = eval("\"#{XRVG_VERSION}\"") # e.g. "1.0.2"
|
48
|
+
#---
|
49
|
+
# Clobber object files and Makefiles generated by extconf.rb.
|
50
|
+
CLOBBER.include("#{EXT_DIR}/**/*.{so,dll,o}", "#{EXT_DIR}/**/Makefile")
|
51
|
+
# Clobber .config generated by setup.rb.
|
52
|
+
CLOBBER.include(".config")
|
53
|
+
|
54
|
+
CLEAN.include("test/**/*.svg", "examples/**/*.svg")
|
55
|
+
#---
|
56
|
+
# Options common to RDocTask AND Gem::Specification.
|
57
|
+
# The --main argument specifies which file appears on the index.html page
|
58
|
+
GENERAL_RDOC_OPTS = {
|
59
|
+
"--title" => "#{PROJECT} API documentation",
|
60
|
+
"--main" => "README"
|
61
|
+
}
|
62
|
+
|
63
|
+
# Additional RDoc formatted files, besides the Ruby source files.
|
64
|
+
RDOC_FILES = FileList["README"]
|
65
|
+
# Remove the following line if you don't want to extract RDoc from
|
66
|
+
# the extension C sources.
|
67
|
+
# RDOC_FILES.include(EXT_SOURCES)
|
68
|
+
|
69
|
+
# Ruby library code.
|
70
|
+
LIB_DIR = "lib"
|
71
|
+
PRE_LIB_FILES = FileList["assertion.rb", "attributable.rb", "color.rb", "frame.rb", "geometry2D.rb", "interpolation.rb", "render.rb", "samplation.rb", "shape.rb", "style.rb", "trace.rb", "utils.rb", "xrvg.rb"]
|
72
|
+
LIB_FILES = FileList["#{LIB_DIR}/*.rb"]
|
73
|
+
|
74
|
+
# Filelist with Test::Unit test cases.
|
75
|
+
TEST_FILES = FileList["test/test_*.rb"]
|
76
|
+
|
77
|
+
# Executable scripts, all non-garbage files under bin/.
|
78
|
+
BIN_FILES = FileList["bin/*"]
|
79
|
+
|
80
|
+
# This filelist is used to create source packages.
|
81
|
+
# Include all Ruby and RDoc files.
|
82
|
+
DIST_FILES = FileList["./examples/*.rb"]
|
83
|
+
DIST_FILES.include(LIB_FILES)
|
84
|
+
DIST_FILES.include("Rakefile", "LICENCE")
|
85
|
+
DIST_FILES.include(BIN_FILES)
|
86
|
+
# DIST_FILES.include("data/**/*", "test/data/**/*")
|
87
|
+
# DIST_FILES.include("#{WEBSITE_DIR}/**/*.{html,css}", "man/*.[0-9]")
|
88
|
+
# Don't package files which are autogenerated by RDocTask
|
89
|
+
DIST_FILES.exclude(/^(\.\/)?#{RDOC_HTML_DIR}(\/|$)/)
|
90
|
+
# Include extension source files.
|
91
|
+
DIST_FILES.include(EXT_DIST_FILES)
|
92
|
+
# Don't package temporary files, perhaps created by tests.
|
93
|
+
DIST_FILES.exclude("**/temp_*", "**/*.tmp", "**/*.svg" )
|
94
|
+
# Don't get into recursion...
|
95
|
+
DIST_FILES.exclude(/^(\.\/)?pkg(\/|$)/)
|
96
|
+
#---
|
97
|
+
# Run the tests if rake is invoked without arguments.
|
98
|
+
task "default" => ["test"]
|
99
|
+
|
100
|
+
test_task_name = HAVE_EXT ? "run-tests" : "test"
|
101
|
+
Rake::TestTask.new(test_task_name) do |t|
|
102
|
+
t.test_files = TEST_FILES
|
103
|
+
t.libs = REQUIRE_PATHS
|
104
|
+
end
|
105
|
+
#---
|
106
|
+
# Set an environment variable with any configuration options you want to
|
107
|
+
# be passed through to "setup.rb config".
|
108
|
+
CONFIG_OPTS = ENV["CONFIG"]
|
109
|
+
if HAVE_EXT
|
110
|
+
file_create ".config" do
|
111
|
+
ruby "setup.rb config #{CONFIG_OPTS}"
|
112
|
+
end
|
113
|
+
|
114
|
+
desc "Configure and make extension. " +
|
115
|
+
"The CONFIG variable is passed to `setup.rb config'"
|
116
|
+
task "make-ext" => ".config" do
|
117
|
+
# The -q option suppresses messages from setup.rb.
|
118
|
+
ruby "setup.rb -q setup"
|
119
|
+
end
|
120
|
+
|
121
|
+
desc "Run tests after making the extension."
|
122
|
+
task "test" do
|
123
|
+
Rake::Task["make-ext"].invoke
|
124
|
+
Rake::Task["run-tests"].invoke
|
125
|
+
end
|
126
|
+
end
|
127
|
+
#---
|
128
|
+
# The "rdoc" task generates API documentation.
|
129
|
+
Rake::RDocTask.new("rdoc") do |t|
|
130
|
+
t.rdoc_files = RDOC_FILES + LIB_FILES
|
131
|
+
t.title = GENERAL_RDOC_OPTS["--title"]
|
132
|
+
t.main = GENERAL_RDOC_OPTS["--main"]
|
133
|
+
t.rdoc_dir = RDOC_HTML_DIR
|
134
|
+
end
|
135
|
+
#---
|
136
|
+
GEM_SPEC = Gem::Specification.new do |s|
|
137
|
+
s.name = UNIX_NAME
|
138
|
+
s.version = PROJECT_VERSION
|
139
|
+
s.summary = PROJECT_SUMMARY
|
140
|
+
s.rubyforge_project = UNIX_NAME
|
141
|
+
s.homepage = "http://#{UNIX_NAME}.rubyforge.org/"
|
142
|
+
s.author = MY_NAME
|
143
|
+
s.email = MY_EMAIL
|
144
|
+
s.files = DIST_FILES
|
145
|
+
s.test_files = TEST_FILES
|
146
|
+
s.executables = BIN_FILES.map { |fn| File.basename(fn) }
|
147
|
+
s.has_rdoc = true
|
148
|
+
s.extra_rdoc_files = RDOC_FILES
|
149
|
+
s.rdoc_options = GENERAL_RDOC_OPTS.to_a.flatten
|
150
|
+
if HAVE_EXT
|
151
|
+
s.extensions = EXTCONF_FILES
|
152
|
+
s.require_paths << EXT_DIR
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
# Now we can generate the package-related tasks.
|
157
|
+
Rake::GemPackageTask.new(GEM_SPEC) do |pkg|
|
158
|
+
# pkg.need_zip = true
|
159
|
+
# pkg.need_tar = true
|
160
|
+
end
|
161
|
+
#---
|
162
|
+
desc "Upload website to RubyForge. " +
|
163
|
+
"scp will prompt for your RubyForge password."
|
164
|
+
task "publish-website" => ["rdoc"] do
|
165
|
+
rubyforge_path = "/var/www/gforge-projects/#{UNIX_NAME}/"
|
166
|
+
sh "scp -r #{WEBSITE_DIR}/* " +
|
167
|
+
"#{RUBYFORGE_USER}@rubyforge.org:#{rubyforge_path}",
|
168
|
+
:verbose => true
|
169
|
+
end
|
170
|
+
#---
|
171
|
+
task "rubyforge-setup" do
|
172
|
+
unless File.exist?(File.join(ENV["HOME"], ".rubyforge"))
|
173
|
+
puts "rubyforge will ask you to edit its config.yml now."
|
174
|
+
puts "Please set the `username' and `password' entries"
|
175
|
+
puts "to your RubyForge username and RubyForge password!"
|
176
|
+
puts "Press ENTER to continue."
|
177
|
+
$stdin.gets
|
178
|
+
sh "rubyforge setup", :verbose => true
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
task "rubyforge-login" => ["rubyforge-setup"] do
|
183
|
+
# Note: We assume that username and password were set in
|
184
|
+
# rubyforge's config.yml.
|
185
|
+
sh "rubyforge login", :verbose => true
|
186
|
+
end
|
187
|
+
|
188
|
+
task "publish-packages" => ["package", "rubyforge-login"] do
|
189
|
+
# Upload packages under pkg/ to RubyForge
|
190
|
+
# This task makes some assumptions:
|
191
|
+
# * You have already created a package on the "Files" tab on the
|
192
|
+
# RubyForge project page. See pkg_name variable below.
|
193
|
+
# * You made entries under package_ids and group_ids for this
|
194
|
+
# project in rubyforge's config.yml. If not, eventually read
|
195
|
+
# "rubyforge --help" and then run "rubyforge setup".
|
196
|
+
pkg_name = ENV["PKG_NAME"] || UNIX_NAME
|
197
|
+
cmd = "rubyforge add_release #{UNIX_NAME} #{pkg_name} " +
|
198
|
+
"#{PROJECT_VERSION} #{UNIX_NAME}-#{PROJECT_VERSION}"
|
199
|
+
cd "pkg" do
|
200
|
+
sh(cmd + ".gem", :verbose => true)
|
201
|
+
sh(cmd + ".tgz", :verbose => true)
|
202
|
+
sh(cmd + ".zip", :verbose => true)
|
203
|
+
end
|
204
|
+
end
|
205
|
+
#---
|
206
|
+
# The "lib" task copy selected files in PRE_LIB_FILES into LIB_DIR directory
|
207
|
+
desc "Copy source files to create ./lib directory"
|
208
|
+
task "lib" do
|
209
|
+
remove_dir LIB_DIR
|
210
|
+
mkdir LIB_DIR
|
211
|
+
PRE_LIB_FILES.to_a.each {|fn| cp( fn, LIB_DIR ) }
|
212
|
+
end
|
213
|
+
|
214
|
+
#---
|
215
|
+
# The "prepare-release" task makes sure your tests run, and then generates
|
216
|
+
# files for a new release.
|
217
|
+
desc "Run tests, generate RDoc and create packages."
|
218
|
+
task "prepare-release" => ["clobber"] do
|
219
|
+
puts "Preparing release of #{PROJECT} version #{VERSION}"
|
220
|
+
Rake::Task["lib"].invoke
|
221
|
+
Rake::Task["test"].invoke
|
222
|
+
Rake::Task["rdoc"].invoke
|
223
|
+
Rake::Task["package"].invoke
|
224
|
+
end
|
225
|
+
|
226
|
+
# The "publish" task is the overarching task for the whole project. It
|
227
|
+
# builds a release and then publishes it to RubyForge.
|
228
|
+
desc "Publish new release of #{PROJECT}"
|
229
|
+
task "publish" => ["prepare-release"] do
|
230
|
+
puts "Uploading documentation..."
|
231
|
+
Rake::Task["publish-website"].invoke
|
232
|
+
puts "Checking for rubyforge command..."
|
233
|
+
`rubyforge --help`
|
234
|
+
if $? == 0
|
235
|
+
puts "Uploading packages..."
|
236
|
+
Rake::Task["publish-packages"].invoke
|
237
|
+
puts "Release done!"
|
238
|
+
else
|
239
|
+
puts "Can't invoke rubyforge command."
|
240
|
+
puts "Either install rubyforge with 'gem install rubyforge'"
|
241
|
+
puts "and retry or upload the package files manually!"
|
242
|
+
end
|
243
|
+
end
|
244
|
+
#---
|
245
|
+
# $ rake -T
|
246
|
+
# rake clean # Remove any temporary products.
|
247
|
+
# rake clobber # Remove any generated file.
|
248
|
+
# rake clobber_package # Remove package products
|
249
|
+
# rake clobber_rdoc # Remove rdoc products
|
250
|
+
# rake package # Build all the packages
|
251
|
+
# rake prepare-release # Run tests, generate RDoc and create packages.
|
252
|
+
# rake publish # Publish new release of MyProject
|
253
|
+
# rake publish-website # Upload website to RubyForge. scp will prompt for your RubyForge password.
|
254
|
+
# rake rdoc # Build the rdoc HTML Files
|
255
|
+
# rake repackage # Force a rebuild of the package files
|
256
|
+
# rake rerdoc # Force a rebuild of the RDOC files
|
257
|
+
# rake test # Run tests for test
|
258
|
+
#---
|
259
|
+
|
260
|
+
# TODO
|
261
|
+
# - add task example checking
|
262
|
+
# - add effective upload with winscp
|
263
|
+
# - add xrvg tutorial documentation publishing (emacs process ?)
|
data/examples/foreach.rb
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
require 'xrvg'
|
2
|
+
|
3
|
+
render = SVGRender[ :filename, "foreach.svg", :background, "white" ]
|
4
|
+
Circle[].samples(10).foreach do |p1,p2|
|
5
|
+
render.add( Circle[:center, p1, :radius, 0.1], Style[ :fill, Color.red ] )
|
6
|
+
render.add( Circle[:center, p2, :radius, 0.2], Style[ :fill, Color.blue ] )
|
7
|
+
render.add( Line[ :exts, [p1,p2] ] )
|
8
|
+
end
|
9
|
+
render.end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
require 'xrvg'
|
2
|
+
|
3
|
+
render = SVGRender[ :filename, "hellocrownrecurse.svg" ]
|
4
|
+
Circle[].samples( 8 ) do |point|
|
5
|
+
Circle[:center, point, :radius, 0.2 ].samples( 8 ) do |point|
|
6
|
+
render.add( Circle[:center, point, :radius, 0.05 ], Style[ :fill, Color.black ] )
|
7
|
+
end
|
8
|
+
end
|
9
|
+
render.end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
require 'xrvg'
|
2
|
+
|
3
|
+
render = SVGRender[ :filename, "palette_circle.svg", :background, "white" ]
|
4
|
+
|
5
|
+
palette = Palette[ :colorlist, [ Color.black, 0.0, Color.blue, 1.0 ] ]
|
6
|
+
[Circle[], palette, (0.1..0.02).random()].samples(25) do |point, color, radius|
|
7
|
+
render.add( Circle[ :center, point, :radius, radius ], Style[ :fill, color ])
|
8
|
+
end
|
9
|
+
|
10
|
+
render.end
|
data/examples/sample.rb
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
require 'xrvg'
|
2
|
+
|
3
|
+
render = SVGRender[ :filename, "palette_circle.svg", :background, "white" ]
|
4
|
+
|
5
|
+
palette = Palette[ :colorlist, [ Color.black, 0.0, Color.blue, 1.0 ] ]
|
6
|
+
[Circle[], palette, (0.1..0.02).random()].samples(25) do |point, color, radius|
|
7
|
+
render.add( Circle[ :center, point, :radius, radius ], Style[ :fill, color ])
|
8
|
+
end
|
9
|
+
|
10
|
+
render.end
|
data/examples/uplets.rb
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
require 'xrvg'
|
2
|
+
|
3
|
+
render = SVGRender[ :filename, "uplets.svg", :background, "white" ]
|
4
|
+
Circle[].samples(10).uplets do |p1,p2|
|
5
|
+
render.add( Circle[:center, p1, :radius, 0.1], Style[ :fill, Color.red ] )
|
6
|
+
render.add( Circle[:center, p2, :radius, 0.2], Style[ :fill, Color.blue ] )
|
7
|
+
render.add( Line[ :exts, [p1,p2] ] )
|
8
|
+
end
|
9
|
+
render.end
|
data/lib/assertion.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
# assertion utility
|
2
|
+
# must be used with care, as expensive
|
3
|
+
#
|
4
|
+
class AssertionError < StandardError
|
5
|
+
end
|
6
|
+
|
7
|
+
#
|
8
|
+
# Assert method, to check for a block, and raise an error if check is not true
|
9
|
+
# Assert("1 is different from 0"){ 1 == 0}
|
10
|
+
def Assert(message=nil, &block)
|
11
|
+
unless(block.call)
|
12
|
+
raise AssertionError, (message || "Assertion failed")
|
13
|
+
end
|
14
|
+
end
|
data/lib/attributable.rb
ADDED
@@ -0,0 +1,152 @@
|
|
1
|
+
#
|
2
|
+
# Module to be able to declare attribute, initializing them by default, with type checking
|
3
|
+
# also define syntaxically simpler builder
|
4
|
+
#
|
5
|
+
# See :
|
6
|
+
# - +Object+
|
7
|
+
# - +Attributable+
|
8
|
+
|
9
|
+
require 'utils'
|
10
|
+
|
11
|
+
#
|
12
|
+
# Object extension to provide the Class[] syntax for building objects, with +Attributable+ module.
|
13
|
+
#
|
14
|
+
# TODO : must be defined only for Class objects !!
|
15
|
+
class Object
|
16
|
+
|
17
|
+
# operator [] definition for shorter and more recognizable object creation syntax.
|
18
|
+
#
|
19
|
+
# Especially useful when creating Attributable dependant objects.
|
20
|
+
# c = Circle[ :center, p, :radius, 0.1 ]
|
21
|
+
def Object.[](*args)
|
22
|
+
return self.new( *args )
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
# Attribute class used by Attributable module
|
28
|
+
#
|
29
|
+
# Attribute syntax :
|
30
|
+
# attribute :attr1 default_value type
|
31
|
+
# with :
|
32
|
+
# - dvalue nil if no default_value (in that case, attribute is said to be required )
|
33
|
+
# - if type is not specified, default_value must be, and type will be the type of this default_value
|
34
|
+
# type can be an Array of types
|
35
|
+
class Attribute
|
36
|
+
attr_accessor :symbol, :default_value, :type
|
37
|
+
|
38
|
+
def initialize( symbol, default_value, type ) #:nodoc:
|
39
|
+
@symbol = symbol
|
40
|
+
@default_value = default_value
|
41
|
+
@type = type
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
# Attributable module
|
47
|
+
#
|
48
|
+
# Allows class attribute definition in a concise and effective way. Can be viewed as a :attr_accessor extension. See also +Attribute+
|
49
|
+
#
|
50
|
+
# Example :
|
51
|
+
# class A
|
52
|
+
# attribute :a 1.0; # type is then Float
|
53
|
+
# attribute :b # attribute is required
|
54
|
+
# end
|
55
|
+
#
|
56
|
+
# a = A[ :a, 10.0, :b, 2.0 ]
|
57
|
+
# a.a => 10.0
|
58
|
+
module Attributable
|
59
|
+
|
60
|
+
module ClassMethods #:nodoc:
|
61
|
+
def init_attributes
|
62
|
+
if not @attributes
|
63
|
+
@attributes = {}
|
64
|
+
newattributes = (self.superclass.ancestors.include? Attributable) ? self.superclass.attributes : {}
|
65
|
+
@attributes = @attributes.merge( newattributes )
|
66
|
+
else
|
67
|
+
# Trace("Attributable::init_attributes self #{self} already initialized")
|
68
|
+
end
|
69
|
+
# Trace("Attributable::init_attributes self #{self} superclass#{self.superclass} superclass ancestors #{self.superclass.ancestors.inspect} result #{@attributes}")
|
70
|
+
end
|
71
|
+
|
72
|
+
def add_attribute( attribute )
|
73
|
+
# Trace("Attributable::add_attribute self #{self} attribute #{attribute.inspect}")
|
74
|
+
init_attributes
|
75
|
+
@attributes[ attribute.symbol ] = attribute
|
76
|
+
end
|
77
|
+
|
78
|
+
def attributes()
|
79
|
+
init_attributes
|
80
|
+
# Trace("Attributable::attributes self #{self} attributes #{@attributes}")
|
81
|
+
return @attributes
|
82
|
+
end
|
83
|
+
|
84
|
+
def checkvaluetype( value, type )
|
85
|
+
typeOK = nil
|
86
|
+
types = type
|
87
|
+
types.each do |type|
|
88
|
+
if value.is_a? type
|
89
|
+
typeOK = true
|
90
|
+
break
|
91
|
+
end
|
92
|
+
end
|
93
|
+
if not typeOK
|
94
|
+
raise( "Attributable::checkvaluetype for class #{self} : default_value #{value.inspect} is not of type #{types.inspect}" )
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def attribute( symbol, default_value=nil, type=nil )
|
99
|
+
if (not type and default_value)
|
100
|
+
type = [default_value.class]
|
101
|
+
elsif type
|
102
|
+
if not type.is_a? Array
|
103
|
+
type = [type]
|
104
|
+
end
|
105
|
+
if default_value
|
106
|
+
checkvaluetype( default_value, type )
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
self.add_attribute( Attribute.new( symbol, default_value, type ) )
|
111
|
+
attr_accessor symbol
|
112
|
+
end
|
113
|
+
|
114
|
+
def instance_variable_set( *args )
|
115
|
+
# Trace("Attributable::instance_variable_set self #{self} args #{args}")
|
116
|
+
super( *args )
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def self.included( receiver ) #:nodoc:
|
121
|
+
# inherit_attributes; does not work because Module is not inherited by subclasses
|
122
|
+
receiver.extend( ClassMethods )
|
123
|
+
end
|
124
|
+
|
125
|
+
def initialize(*args) #:nodoc:
|
126
|
+
# first check if every specified attribute is meaningfull for the class
|
127
|
+
args.foreach do |symbol, value|
|
128
|
+
if not self.class.attributes.key? symbol
|
129
|
+
raise( "Attributable::initialize for class #{self} does not have attribute #{symbol}" )
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
# then check specification coherence, and do initialization
|
134
|
+
spec = Hash[ *args ]
|
135
|
+
self.class.attributes.each_pair do |symbol, attr|
|
136
|
+
if spec.key? symbol
|
137
|
+
value = spec[ symbol ]
|
138
|
+
if attr.type
|
139
|
+
self.class.checkvaluetype( value, attr.type )
|
140
|
+
end
|
141
|
+
# do init after checking
|
142
|
+
self.method("#{symbol.to_s}=").call(value)
|
143
|
+
else
|
144
|
+
if not attr.default_value
|
145
|
+
raise( "Attributable::initialize for class #{self} : attribute #{symbol} is required : attributes #{self.class.attributes.inspect}" )
|
146
|
+
end
|
147
|
+
self.method("#{symbol.to_s}=").call(attr.default_value)
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
end
|