ruby-processing 1.0.2 → 1.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +12 -0
- data/lib/ruby-processing.rb +2 -1
- data/lib/ruby-processing/app.rb +7 -5
- data/lib/ruby-processing/exporters/creator.rb +7 -4
- data/lib/ruby-processing/helpers/numeric.rb +11 -0
- data/lib/ruby-processing/helpers/string.rb +8 -0
- data/lib/ruby-processing/runner.rb +11 -10
- data/lib/ruby-processing/runners/watch.rb +33 -0
- data/samples/bezier_playground.rb +243 -0
- data/samples/flight_patterns.rb +1 -1
- data/samples/learning_processing/chapter_16/01_display_video.rb +1 -1
- data/samples/learning_processing/chapter_16/02_manipulate_video_image.rb +1 -1
- data/samples/processing_app/basics/arrays/array.rb +41 -0
- data/samples/processing_app/basics/arrays/array_2d.rb +38 -0
- data/samples/processing_app/basics/arrays/array_objects.rb +67 -0
- data/samples/processing_app/basics/color/brightness.rb +30 -0
- data/samples/processing_app/basics/color/color_wheel.rb +97 -0
- data/samples/processing_app/basics/color/creating.rb +37 -0
- data/samples/processing_app/basics/color/hue.rb +29 -0
- data/samples/processing_app/basics/color/linear_gradient.rb +47 -0
- data/samples/processing_app/basics/color/radial_gradient.rb +52 -0
- data/samples/processing_app/basics/color/reading/data/cait.jpg +0 -0
- data/samples/processing_app/basics/color/reading/reading.rb +43 -0
- data/samples/processing_app/basics/color/relativity.rb +38 -0
- data/samples/processing_app/basics/color/saturation.rb +35 -0
- data/samples/processing_app/basics/color/wave_gradient.rb +45 -0
- data/samples/processing_app/basics/control/conditionals1.rb +51 -0
- data/samples/processing_app/basics/control/conditionals2.rb +44 -0
- data/samples/processing_app/basics/control/embedded_iteration.rb +42 -0
- data/samples/processing_app/basics/control/iteration.rb +61 -0
- data/samples/processing_app/basics/control/logical_operators.rb +59 -0
- data/samples/processing_app/basics/data/characters_strings/characters_strings.rb +87 -0
- data/samples/processing_app/basics/data/characters_strings/data/Eureka-90.vlw +0 -0
- data/samples/processing_app/basics/data/characters_strings/data/rathausFrog.jpg +0 -0
- data/samples/processing_app/basics/data/datatype_conversion.rb +45 -0
- data/samples/processing_app/basics/data/integers_floats.rb +34 -0
- data/samples/processing_app/basics/data/true_false.rb +37 -0
- data/samples/processing_app/basics/data/variable_scope.rb +80 -0
- data/samples/processing_app/basics/data/variables.rb +40 -0
- data/samples/processing_app/basics/form/bezier.rb +23 -0
- data/samples/processing_app/basics/form/bezier_ellipse.rb +110 -0
- data/samples/processing_app/basics/form/pie_chart.rb +31 -0
- data/samples/processing_app/basics/form/points_lines.rb +37 -0
- data/samples/processing_app/basics/form/shape_primitives.rb +25 -0
- data/samples/processing_app/basics/form/triangle_strip.rb +43 -0
- data/samples/processing_app/basics/form/vertices.rb +51 -0
- data/samples/processing_app/basics/image/alphamask.rb +23 -0
- data/samples/processing_app/basics/image/background_image.rb +30 -0
- data/samples/processing_app/basics/image/create_image.rb +23 -0
- data/samples/processing_app/basics/image/data/construct.jpg +0 -0
- data/samples/processing_app/basics/image/data/eames.jpg +0 -0
- data/samples/processing_app/basics/image/data/jelly.jpg +0 -0
- data/samples/processing_app/basics/image/data/mask.jpg +0 -0
- data/samples/processing_app/basics/image/data/milan_rubbish.jpg +0 -0
- data/samples/processing_app/basics/image/data/teddy.gif +0 -0
- data/samples/processing_app/basics/image/data/test.jpg +0 -0
- data/samples/processing_app/basics/image/data/wash.jpg +0 -0
- data/samples/processing_app/basics/image/load_display_image.rb +25 -0
- data/samples/processing_app/basics/image/pointillism.rb +30 -0
- data/samples/processing_app/basics/image/request_image.rb +71 -0
- data/samples/processing_app/basics/image/sprite.rb +38 -0
- data/samples/processing_app/basics/image/transparency.rb +27 -0
- data/samples/processing_app/basics/input/clock.rb +46 -0
- data/samples/processing_app/basics/input/constrain.rb +39 -0
- data/samples/processing_app/basics/input/easing.rb +33 -0
- data/samples/processing_app/basics/input/keyboard.rb +36 -0
- data/samples/processing_app/basics/input/keyboard_2.rb +45 -0
- data/samples/processing_app/basics/input/keyboard_functions.rb +87 -0
- data/samples/processing_app/basics/input/milliseconds.rb +25 -0
- data/samples/processing_app/basics/input/mouse_1d.rb +34 -0
- data/samples/processing_app/basics/input/mouse_2d.rb +25 -0
- data/samples/processing_app/basics/input/mouse_functions.rb +73 -0
- data/samples/processing_app/basics/input/mouse_press.rb +21 -0
- data/samples/processing_app/basics/input/mouse_signals.rb +45 -0
- data/samples/processing_app/basics/input/storing_input.rb +39 -0
- data/samples/processing_app/basics/math/additive_wave.rb +66 -0
- data/samples/processing_app/basics/math/arctangent.rb +54 -0
- data/samples/processing_app/topics/simulate/chain.rb +82 -0
- data/samples/processing_app/topics/simulate/multiple_particle_systems.rb +166 -0
- data/samples/processing_app/topics/simulate/simple_particle_system.rb +113 -0
- data/samples/processing_app/topics/simulate/spring.rb +85 -0
- data/samples/processing_app/topics/simulate/springs.rb +125 -0
- metadata +93 -2
data/CHANGELOG
CHANGED
@@ -1,3 +1,15 @@
|
|
1
|
+
v1.0.3 Tweaks and Tuneups...
|
2
|
+
* "rp5 watch" is now a bit more robust, and tries to reload every
|
3
|
+
* file, global, and constant that it thinks it needs to.
|
4
|
+
* Many, many examples have been contributed by Marc Chung,
|
5
|
+
Peter Krenn, and Florian Jenett.
|
6
|
+
* Andreas Haller contributed a patch that added Ruby-1.9 compatibility.
|
7
|
+
* The render mode now defaults to JAVA2D, as does Processing.
|
8
|
+
* "rp5 create" now informs you of the file it just created.
|
9
|
+
* "key" now returns a character, if ASCII and the integer value otherwise,
|
10
|
+
mirroring Processing's behavior.
|
11
|
+
* Numbers now have the methods 'degrees' and 'radians', for ease.
|
12
|
+
|
1
13
|
v1.0.2 Bugfixes and Java Args...
|
2
14
|
* Application exporting, long plagued, should now be a little
|
3
15
|
closer to rock-solid. If you need to pass command-line options
|
data/lib/ruby-processing.rb
CHANGED
@@ -8,10 +8,11 @@ unless defined? RP5_ROOT
|
|
8
8
|
end
|
9
9
|
|
10
10
|
require 'ruby-processing/helpers/string'
|
11
|
+
require 'ruby-processing/helpers/numeric'
|
11
12
|
|
12
13
|
# The top-level namespace, a home for all Ruby-Processing classes.
|
13
14
|
module Processing
|
14
|
-
VERSION = [1,0,
|
15
|
+
VERSION = [1,0,3] unless defined? Processing::VERSION
|
15
16
|
|
16
17
|
# Returns the current version of Ruby-Processing.
|
17
18
|
def self.version
|
data/lib/ruby-processing/app.rb
CHANGED
@@ -8,7 +8,7 @@ module Processing
|
|
8
8
|
|
9
9
|
# Conditionally load core.jar
|
10
10
|
require "#{RP5_ROOT}/lib/core/core.jar" unless Object.const_defined?(:JRUBY_APPLET)
|
11
|
-
|
11
|
+
import "processing.core"
|
12
12
|
|
13
13
|
# This is the main Ruby-Processing class, and is what you'll
|
14
14
|
# inherit from when you create a sketch. This class can call
|
@@ -20,11 +20,11 @@ module Processing
|
|
20
20
|
class App < PApplet
|
21
21
|
include Math
|
22
22
|
|
23
|
-
|
23
|
+
import "javax.swing.JFrame"
|
24
24
|
|
25
25
|
# Include some processing classes that we'd like to use:
|
26
26
|
%w(PShape PImage PGraphics PFont PVector).each do |klass|
|
27
|
-
|
27
|
+
import "processing.core.#{klass}"
|
28
28
|
end
|
29
29
|
|
30
30
|
# Alias some methods for familiarity for Shoes coders.
|
@@ -175,7 +175,7 @@ module Processing
|
|
175
175
|
:full_screen => false
|
176
176
|
}.merge(options)
|
177
177
|
@width, @height, @title = options[:width], options[:height], options[:title]
|
178
|
-
@render_mode =
|
178
|
+
@render_mode = JAVA2D
|
179
179
|
determine_how_to_display options
|
180
180
|
end
|
181
181
|
|
@@ -235,10 +235,12 @@ module Processing
|
|
235
235
|
|
236
236
|
|
237
237
|
# Fix java conversion problems getting the last key
|
238
|
+
# If it's ASCII, return the character, otherwise the integer
|
238
239
|
def key
|
239
240
|
field = java_class.declared_field 'key'
|
240
241
|
app = Java.ruby_to_java self
|
241
|
-
field.value
|
242
|
+
int = field.value(app)
|
243
|
+
int < 256 ? int.chr : int
|
242
244
|
end
|
243
245
|
|
244
246
|
|
@@ -9,7 +9,10 @@ module Processing
|
|
9
9
|
main_file = File.basename(path, ".rb")
|
10
10
|
# Check to make sure that the main file exists
|
11
11
|
already_exists = File.exists?(path) || File.exists?("#{File.dirname(path)}/#{main_file.underscore}.rb")
|
12
|
-
|
12
|
+
if already_exists
|
13
|
+
puts "That sketch already exists."
|
14
|
+
exit
|
15
|
+
end
|
13
16
|
|
14
17
|
# Get the substitutions
|
15
18
|
@name = main_file.camelize
|
@@ -23,9 +26,9 @@ module Processing
|
|
23
26
|
mkdir_p dir
|
24
27
|
template = File.new("#{RP5_ROOT}/lib/templates/create/blank_sketch.rb.erb")
|
25
28
|
rendered = render_erb_from_string_with_binding(template.read, binding)
|
26
|
-
File.
|
27
|
-
|
28
|
-
|
29
|
+
full_path = File.join(dir, "#{@file_name}.rb")
|
30
|
+
File.open(full_path, "w") {|f| f.print(rendered) }
|
31
|
+
puts "Created Sketch \"#{@title}\" in #{full_path.sub(/\A\.\//, '')}"
|
29
32
|
end
|
30
33
|
|
31
34
|
# Show the help/usage message for create.
|
@@ -37,16 +37,17 @@ module Processing
|
|
37
37
|
# Dispatch central.
|
38
38
|
def execute!
|
39
39
|
case @options.action
|
40
|
-
when 'run'
|
41
|
-
when 'watch'
|
42
|
-
when 'create'
|
43
|
-
when 'live'
|
44
|
-
when 'app'
|
45
|
-
when 'applet'
|
46
|
-
when 'unpack'
|
47
|
-
when /-v/
|
48
|
-
when /-h/
|
49
|
-
else
|
40
|
+
when 'run' then run(@options.path)
|
41
|
+
when 'watch' then watch(@options.path)
|
42
|
+
when 'create' then create(@options.path, @options.args)
|
43
|
+
when 'live' then live(@options.path)
|
44
|
+
when 'app' then app(@options.path)
|
45
|
+
when 'applet' then applet(@options.path)
|
46
|
+
when 'unpack' then unpack(@options.path)
|
47
|
+
when /-v/ then show_version
|
48
|
+
when /-h/ then show_help
|
49
|
+
else
|
50
|
+
show_help
|
50
51
|
end
|
51
52
|
end
|
52
53
|
|
@@ -10,10 +10,12 @@ module Processing
|
|
10
10
|
def initialize(sketch)
|
11
11
|
@file = sketch
|
12
12
|
@time = Time.now
|
13
|
+
record_state_of_ruby
|
13
14
|
load @file
|
14
15
|
start_watching
|
15
16
|
end
|
16
17
|
|
18
|
+
|
17
19
|
# Kicks off a thread to watch the sketch, reloading Ruby-Processing
|
18
20
|
# and restarting the sketch whenever it changes.
|
19
21
|
def start_watching
|
@@ -23,6 +25,7 @@ module Processing
|
|
23
25
|
if file_mtime > @time
|
24
26
|
@time = file_mtime
|
25
27
|
Processing::App.wipe_out_current_app!
|
28
|
+
rewind_to_recorded_state
|
26
29
|
GC.start
|
27
30
|
begin
|
28
31
|
load @file
|
@@ -36,6 +39,36 @@ module Processing
|
|
36
39
|
thread.join
|
37
40
|
end
|
38
41
|
|
42
|
+
|
43
|
+
# Do the best we can to take a picture of the current Ruby interpreter.
|
44
|
+
# For now, this means top-level constants and loaded .rb files.
|
45
|
+
def record_state_of_ruby
|
46
|
+
@saved_constants = Object.send(:constants).dup
|
47
|
+
@saved_load_paths = $LOAD_PATH.dup
|
48
|
+
@saved_features = $LOADED_FEATURES.dup
|
49
|
+
@saved_globals = Kernel.global_variables.dup
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
# Try to go back to the recorded Ruby state.
|
54
|
+
def rewind_to_recorded_state
|
55
|
+
new_constants = Object.send(:constants).reject {|c| @saved_constants.include?(c) }
|
56
|
+
new_load_paths = $LOAD_PATH.reject {|p| @saved_load_paths.include?(p) }
|
57
|
+
new_features = $LOADED_FEATURES.reject {|f| @saved_features.include?(f) }
|
58
|
+
new_globals = Kernel.global_variables.reject {|g| @saved_globals.include?(g) }
|
59
|
+
|
60
|
+
new_constants.each {|c| Object.send(:remove_const, c) }
|
61
|
+
new_load_paths.each {|p| $LOAD_PATH.delete(p) }
|
62
|
+
new_features.each {|f| $LOADED_FEATURES.delete(f) }
|
63
|
+
new_globals.each do |g|
|
64
|
+
begin
|
65
|
+
eval("#{g} = nil") # There's no way to undef a global variable in Ruby
|
66
|
+
rescue NameError => e
|
67
|
+
# Some globals are read-only, and we can't set them to nil.
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
39
72
|
end
|
40
73
|
end
|
41
74
|
|
@@ -0,0 +1,243 @@
|
|
1
|
+
require 'ruby-processing'
|
2
|
+
|
3
|
+
# A Bezier playground. Click to shape the curve. Drag to move it.
|
4
|
+
# Arrows toggle between curves, delete removes them.
|
5
|
+
# You can print out the parametric equations for t = 0..1
|
6
|
+
|
7
|
+
|
8
|
+
module Math
|
9
|
+
|
10
|
+
def self.overlaps(x, y, point_x, point_y)
|
11
|
+
Math.sqrt((x-point_x)**2 + (y-point_y)**2) < Bezier::RADIUS
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
class Curve
|
18
|
+
|
19
|
+
attr_accessor :x1, :y1, :c1x, :c1y, :c2x, :c2y, :x2, :y2
|
20
|
+
|
21
|
+
def initialize
|
22
|
+
@x1, @y1, @x2, @y2 = Bezier::X1, Bezier::Y1, Bezier::X2, Bezier::Y2
|
23
|
+
set_control_points( Bezier::X1+30, Bezier::Y1, Bezier::X2-30, Bezier::Y2)
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
def contains(x, y)
|
28
|
+
return :one if Math.overlaps(@x1, @y1, x, y)
|
29
|
+
return :two if Math.overlaps(@x2, @y2, x, y)
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
def all_points
|
34
|
+
return x1, y1, c1x, c1y, c2x, c2y, x2, y2
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
def control_points
|
39
|
+
return c1x, c1y, c2x, c2y
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
def set_control_points(*points)
|
44
|
+
@c1x, @c1y, @c2x, @c2y = *points
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
def draw
|
49
|
+
$app.bezier *all_points
|
50
|
+
$app.oval @x1, @y1, 3, 3
|
51
|
+
$app.oval @x2, @y2, 3, 3
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
def print_equation
|
56
|
+
p = all_points.map {|p| p.to_i }
|
57
|
+
puts ""
|
58
|
+
puts "*** line ##{$app.curves.index(self) + 1} ***"
|
59
|
+
puts "x = (1-t)^3 #{p[0]} + 3(1-t)^2 t#{p[2]} + 3(1-t)t^2 #{p[4]} + t^3 #{p[6]}"
|
60
|
+
puts "y = -1 * ((1-t)^3 #{p[1]} + 3(1-t)^2 t#{p[3]} + 3(1-t)t^2 #{p[5]} + t^3 #{p[7]})"
|
61
|
+
puts ""
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
|
67
|
+
class Bezier < Processing::App
|
68
|
+
|
69
|
+
attr_accessor :curves, :c1x, :c1y, :c2x, :c2y
|
70
|
+
|
71
|
+
X1, Y1, X2, Y2 = 50.0, 50.0, 250.0, 250.0
|
72
|
+
REDDISH = [250, 100, 100]
|
73
|
+
RADIUS = 7
|
74
|
+
|
75
|
+
load_library :control_panel
|
76
|
+
|
77
|
+
def setup
|
78
|
+
smooth
|
79
|
+
@curves = []
|
80
|
+
|
81
|
+
control_panel do |c|
|
82
|
+
c.button :new_curve
|
83
|
+
c.button :print_equations
|
84
|
+
end
|
85
|
+
|
86
|
+
generate_curve
|
87
|
+
end
|
88
|
+
|
89
|
+
|
90
|
+
def print_equations
|
91
|
+
@curves.each {|c| c.print_equation }
|
92
|
+
end
|
93
|
+
|
94
|
+
|
95
|
+
def control_points
|
96
|
+
return c1x, c1y, c2x, c2y
|
97
|
+
end
|
98
|
+
|
99
|
+
|
100
|
+
def set_control_points(*points)
|
101
|
+
@c1x, @c1y, @c2x, @c2y = points.any? ? points : [X1, Y1, X2, Y2]
|
102
|
+
end
|
103
|
+
|
104
|
+
|
105
|
+
def generate_curve
|
106
|
+
@curves << @current_curve = Curve.new
|
107
|
+
@current = @curves.length - 1
|
108
|
+
set_control_points(*current_curve.control_points)
|
109
|
+
end
|
110
|
+
|
111
|
+
|
112
|
+
def current_curve
|
113
|
+
@curves[@current]
|
114
|
+
end
|
115
|
+
|
116
|
+
|
117
|
+
def new_curve
|
118
|
+
current_curve.set_control_points(c1x, c1y, c2x, c2y)
|
119
|
+
generate_curve
|
120
|
+
end
|
121
|
+
|
122
|
+
|
123
|
+
def clicked_control_point?
|
124
|
+
x, y = mouse_x, mouse_y
|
125
|
+
return :one if Math.overlaps(@c1x, @c1y, x, y)
|
126
|
+
return :two if Math.overlaps(@c2x, @c2y, x, y)
|
127
|
+
end
|
128
|
+
|
129
|
+
|
130
|
+
def key_pressed
|
131
|
+
case keyCode
|
132
|
+
when 8 # Delete the current line
|
133
|
+
return if @curves.length <= 1
|
134
|
+
@curves.delete(current_curve)
|
135
|
+
@current = @curves.length - 1
|
136
|
+
when LEFT # Flip forward
|
137
|
+
@current = (@current + 1) % @curves.length
|
138
|
+
when RIGHT # Flip back
|
139
|
+
@current = (@current - 1) % @curves.length
|
140
|
+
end
|
141
|
+
set_control_points(*current_curve.control_points)
|
142
|
+
end
|
143
|
+
|
144
|
+
|
145
|
+
def mouse_pressed
|
146
|
+
switch_curve_if_endpoint_clicked
|
147
|
+
@control = clicked_control_point?
|
148
|
+
return if @control
|
149
|
+
curve = @curves.detect {|c| c.contains(mouse_x, mouse_y) }
|
150
|
+
@end_point = curve.contains(mouse_x, mouse_y) if curve
|
151
|
+
end
|
152
|
+
|
153
|
+
|
154
|
+
def mouse_released
|
155
|
+
@control, @end_point = nil, nil
|
156
|
+
end
|
157
|
+
|
158
|
+
|
159
|
+
def mouse_dragged
|
160
|
+
offs = compute_offsets
|
161
|
+
return if offs.map {|o| o.abs }.max > 100
|
162
|
+
return move_control_point(*offs) if @control
|
163
|
+
return move_end_point(*offs) && move_control_point(*offs) if @end_point
|
164
|
+
move_current_curve(*offs)
|
165
|
+
end
|
166
|
+
|
167
|
+
|
168
|
+
def switch_curve_if_endpoint_clicked
|
169
|
+
become = @curves.detect {|c| c.contains(mouse_x, mouse_y) }
|
170
|
+
return unless become && become != current_curve
|
171
|
+
current_curve.set_control_points(*control_points)
|
172
|
+
self.set_control_points(*become.control_points)
|
173
|
+
@current = @curves.index(become)
|
174
|
+
end
|
175
|
+
|
176
|
+
|
177
|
+
def move_current_curve(x_off, y_off)
|
178
|
+
@c1x += x_off; @c2x += x_off
|
179
|
+
@c1y += y_off; @c2y += y_off
|
180
|
+
current_curve.set_control_points(*control_points)
|
181
|
+
current_curve.x1 += x_off; current_curve.x2 += x_off
|
182
|
+
current_curve.y1 += y_off; current_curve.y2 += y_off
|
183
|
+
end
|
184
|
+
|
185
|
+
|
186
|
+
def move_control_point(x_off, y_off)
|
187
|
+
case @control || @end_point
|
188
|
+
when :one : @c1x += x_off and @c1y += y_off
|
189
|
+
when :two : @c2x += x_off and @c2y += y_off
|
190
|
+
end
|
191
|
+
current_curve.set_control_points(*control_points)
|
192
|
+
end
|
193
|
+
|
194
|
+
|
195
|
+
def move_end_point(x_off, y_off)
|
196
|
+
c = current_curve
|
197
|
+
case @end_point
|
198
|
+
when :one : c.x1 += x_off and c.y1 += y_off
|
199
|
+
when :two : c.x2 += x_off and c.y2 += y_off
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
|
204
|
+
def compute_offsets
|
205
|
+
return mouse_x - pmouse_x, mouse_y - pmouse_y
|
206
|
+
end
|
207
|
+
|
208
|
+
|
209
|
+
def draw_curves
|
210
|
+
stroke 255
|
211
|
+
no_fill
|
212
|
+
stroke_width 2
|
213
|
+
@curves.each {|curve| curve.draw }
|
214
|
+
end
|
215
|
+
|
216
|
+
|
217
|
+
def draw_current_control_points
|
218
|
+
fill *REDDISH
|
219
|
+
no_stroke
|
220
|
+
oval @c1x, @c1y, 5, 5
|
221
|
+
oval @c2x, @c2y, 5, 5
|
222
|
+
end
|
223
|
+
|
224
|
+
|
225
|
+
def draw_control_tangent_lines
|
226
|
+
c = current_curve
|
227
|
+
stroke *REDDISH
|
228
|
+
stroke_width 1
|
229
|
+
line @c1x, @c1y, c.x1, c.y1
|
230
|
+
line @c2x, @c2y, c.x2, c.y2
|
231
|
+
end
|
232
|
+
|
233
|
+
|
234
|
+
def draw
|
235
|
+
background 50
|
236
|
+
draw_control_tangent_lines
|
237
|
+
draw_curves
|
238
|
+
draw_current_control_points
|
239
|
+
end
|
240
|
+
|
241
|
+
end
|
242
|
+
|
243
|
+
Bezier.new :title => "Bezier", :width => 700, :height => 700
|